<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>TypeScript入门111 | 星月前端博客</title>
    <meta name="generator" content="VuePress 1.8.2">
    <link rel="icon" href="/favicon.ico">
    <meta name="description" content="The top of the mountain is not the end, nor is the other mountain.">
    <meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
    
    <link rel="preload" href="/assets/css/0.styles.f057962c.css" as="style"><link rel="preload" href="/assets/js/app.b0d6e6c9.js" as="script"><link rel="preload" href="/assets/js/3.3f705cf6.js" as="script"><link rel="preload" href="/assets/js/1.5432b32a.js" as="script"><link rel="preload" href="/assets/js/17.39fb3a22.js" as="script"><link rel="prefetch" href="/assets/js/10.a8f43ca8.js"><link rel="prefetch" href="/assets/js/11.f3a618ea.js"><link rel="prefetch" href="/assets/js/12.b0d83b4c.js"><link rel="prefetch" href="/assets/js/13.f1fb4696.js"><link rel="prefetch" href="/assets/js/14.e5bc98a2.js"><link rel="prefetch" href="/assets/js/15.50519e37.js"><link rel="prefetch" href="/assets/js/16.3c6a720c.js"><link rel="prefetch" href="/assets/js/18.76eb3752.js"><link rel="prefetch" href="/assets/js/19.7e9cf824.js"><link rel="prefetch" href="/assets/js/20.91bdeca4.js"><link rel="prefetch" href="/assets/js/21.136cc362.js"><link rel="prefetch" href="/assets/js/22.ec4f40f8.js"><link rel="prefetch" href="/assets/js/23.50127d3e.js"><link rel="prefetch" href="/assets/js/24.793b4c66.js"><link rel="prefetch" href="/assets/js/25.e2402b1b.js"><link rel="prefetch" href="/assets/js/26.cda4008e.js"><link rel="prefetch" href="/assets/js/27.8f1f302e.js"><link rel="prefetch" href="/assets/js/28.15cd65f2.js"><link rel="prefetch" href="/assets/js/29.00adce9e.js"><link rel="prefetch" href="/assets/js/30.c29d2b5d.js"><link rel="prefetch" href="/assets/js/31.40db97f7.js"><link rel="prefetch" href="/assets/js/32.70ed39cf.js"><link rel="prefetch" href="/assets/js/33.b0f7cfc3.js"><link rel="prefetch" href="/assets/js/34.f0a63370.js"><link rel="prefetch" href="/assets/js/35.88e20dad.js"><link rel="prefetch" href="/assets/js/36.13f74559.js"><link rel="prefetch" href="/assets/js/37.1d442fc4.js"><link rel="prefetch" href="/assets/js/38.84077197.js"><link rel="prefetch" href="/assets/js/39.51512938.js"><link rel="prefetch" href="/assets/js/4.3ce47df9.js"><link rel="prefetch" href="/assets/js/40.1f3d0e52.js"><link rel="prefetch" href="/assets/js/41.8e4ee580.js"><link rel="prefetch" href="/assets/js/42.690cbafe.js"><link rel="prefetch" href="/assets/js/43.c4aa2221.js"><link rel="prefetch" href="/assets/js/44.fb378084.js"><link rel="prefetch" href="/assets/js/45.77700693.js"><link rel="prefetch" href="/assets/js/46.d507cb48.js"><link rel="prefetch" href="/assets/js/47.e3a1008a.js"><link rel="prefetch" href="/assets/js/48.d6c9c78e.js"><link rel="prefetch" href="/assets/js/49.4667e7c0.js"><link rel="prefetch" href="/assets/js/5.6d641d4f.js"><link rel="prefetch" href="/assets/js/50.8ec4f4f5.js"><link rel="prefetch" href="/assets/js/51.d9305c51.js"><link rel="prefetch" href="/assets/js/52.db11222b.js"><link rel="prefetch" href="/assets/js/53.61d62d9d.js"><link rel="prefetch" href="/assets/js/54.f20b6c65.js"><link rel="prefetch" href="/assets/js/55.0a4f147e.js"><link rel="prefetch" href="/assets/js/56.cd32d35a.js"><link rel="prefetch" href="/assets/js/57.a5fde1bb.js"><link rel="prefetch" href="/assets/js/58.a0a97490.js"><link rel="prefetch" href="/assets/js/59.1bb4fab1.js"><link rel="prefetch" href="/assets/js/6.5f336290.js"><link rel="prefetch" href="/assets/js/60.e6987c2a.js"><link rel="prefetch" href="/assets/js/61.419fcdc8.js"><link rel="prefetch" href="/assets/js/62.5a9d4e12.js"><link rel="prefetch" href="/assets/js/63.be6ca5ce.js"><link rel="prefetch" href="/assets/js/64.8aef8f94.js"><link rel="prefetch" href="/assets/js/65.16450833.js"><link rel="prefetch" href="/assets/js/66.2969e029.js"><link rel="prefetch" href="/assets/js/67.e3a3c472.js"><link rel="prefetch" href="/assets/js/68.6ff65261.js"><link rel="prefetch" href="/assets/js/69.cf4da88b.js"><link rel="prefetch" href="/assets/js/7.6a1d4e29.js"><link rel="prefetch" href="/assets/js/70.1472620a.js"><link rel="prefetch" href="/assets/js/71.1e7cb0a1.js"><link rel="prefetch" href="/assets/js/72.2bf85313.js"><link rel="prefetch" href="/assets/js/73.d9cb4d96.js"><link rel="prefetch" href="/assets/js/74.0c536977.js"><link rel="prefetch" href="/assets/js/75.4f82c6a8.js"><link rel="prefetch" href="/assets/js/76.42f3f0b7.js"><link rel="prefetch" href="/assets/js/77.70961c41.js"><link rel="prefetch" href="/assets/js/78.2f45f2fc.js"><link rel="prefetch" href="/assets/js/79.a68a9b1c.js"><link rel="prefetch" href="/assets/js/8.378e22b1.js"><link rel="prefetch" href="/assets/js/80.6cb339b8.js"><link rel="prefetch" href="/assets/js/81.5849f124.js"><link rel="prefetch" href="/assets/js/82.f5531d2d.js"><link rel="prefetch" href="/assets/js/83.47badffa.js"><link rel="prefetch" href="/assets/js/84.dece7e94.js"><link rel="prefetch" href="/assets/js/85.d9e7f122.js"><link rel="prefetch" href="/assets/js/86.233d7088.js"><link rel="prefetch" href="/assets/js/87.ce5dff2e.js"><link rel="prefetch" href="/assets/js/88.f976bef7.js"><link rel="prefetch" href="/assets/js/89.8473e540.js"><link rel="prefetch" href="/assets/js/9.9eb4a88c.js"><link rel="prefetch" href="/assets/js/90.d6288b36.js"><link rel="prefetch" href="/assets/js/91.989f4dea.js"><link rel="prefetch" href="/assets/js/92.6ff507f9.js">
    <link rel="stylesheet" href="/assets/css/0.styles.f057962c.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container no-sidebar" data-v-5bb33761><div data-v-5bb33761><div class="password-shadow password-wrapper-out" style="display:none;" data-v-59e6cb88 data-v-5bb33761 data-v-5bb33761><h3 class="title" data-v-59e6cb88>星月前端博客</h3> <p class="description" data-v-59e6cb88>The top of the mountain is not the end, nor is the other mountain.</p> <label id="box" class="inputBox" data-v-59e6cb88><input type="password" value="" data-v-59e6cb88> <span data-v-59e6cb88>Konck! Knock!</span> <button data-v-59e6cb88>OK</button></label> <div class="footer" data-v-59e6cb88><span data-v-59e6cb88><i class="iconfont reco-theme" data-v-59e6cb88></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-59e6cb88>vuePress-theme-reco</a></span> <span data-v-59e6cb88><i class="iconfont reco-copyright" data-v-59e6cb88></i> <a data-v-59e6cb88><span data-v-59e6cb88>星月</span>
          
        <!---->
        2022
      </a></span></div></div> <div class="hide" data-v-5bb33761><header class="navbar" data-v-5bb33761><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><img src="/logo.png" alt="星月前端博客" class="logo"> <span class="site-name">星月前端博客</span></a> <div class="links"><div class="color-picker"><a class="color-button"><i class="iconfont reco-color"></i></a> <div class="color-picker-menu" style="display:none;"><div class="mode-options"><h4 class="title">Choose mode</h4> <ul class="color-mode-options"><li class="dark">dark</li><li class="auto active">auto</li><li class="light">light</li></ul></div></div></div> <div class="search-box"><i class="iconfont reco-search"></i> <input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="/" class="nav-link"><i class="iconfont reco-home"></i>
  首页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-category"></i>
      博客
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/ES6模块化与异步编程/" class="nav-link"><i class="undefined"></i>
  ES6模块化与异步编程
</a></li><li class="dropdown-item"><!----> <a href="/categories/css/" class="nav-link"><i class="undefined"></i>
  css
</a></li><li class="dropdown-item"><!----> <a href="/categories/TypeScript/" class="nav-link"><i class="undefined"></i>
  TypeScript
</a></li><li class="dropdown-item"><!----> <a href="/categories/html/" class="nav-link"><i class="undefined"></i>
  html
</a></li><li class="dropdown-item"><!----> <a href="/categories/JavaScript/" class="nav-link"><i class="undefined"></i>
  JavaScript
</a></li><li class="dropdown-item"><!----> <a href="/categories/Node.js/" class="nav-link"><i class="undefined"></i>
  Node.js
</a></li><li class="dropdown-item"><!----> <a href="/categories/Vue2/" class="nav-link"><i class="undefined"></i>
  Vue2
</a></li><li class="dropdown-item"><!----> <a href="/categories/Vue3/" class="nav-link"><i class="undefined"></i>
  Vue3
</a></li><li class="dropdown-item"><!----> <a href="/categories/webpack/" class="nav-link"><i class="undefined"></i>
  webpack
</a></li></ul></div></div><div class="nav-item"><a href="/tag/" class="nav-link"><i class="iconfont reco-tag"></i>
  标签
</a></div><div class="nav-item"><a href="/timeline/" class="nav-link"><i class="iconfont reco-date"></i>
  时间线
</a></div><div class="nav-item"><a href="/docs/theme-reco/" class="nav-link"><i class="iconfont reco-message"></i>
  随记
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-message"></i>
      联系方式
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://github.com/858399075" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-github"></i>
  GitHub
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://gitee.com/xingyueqianduan" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-github"></i>
  Gitee
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://blog.yhxweb.top/" target="_blank" rel="noopener noreferrer" class="nav-link external"><i></i>
  QQ:76120220
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://blog.yhxweb.top/" target="_blank" rel="noopener noreferrer" class="nav-link external"><i></i>
  WX:15237156071
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask" data-v-5bb33761></div> <aside class="sidebar" data-v-5bb33761><div class="personal-info-wrapper" data-v-1fad0c41 data-v-5bb33761><img src="/avatar.png" alt="author-avatar" class="personal-img" data-v-1fad0c41> <h3 class="name" data-v-1fad0c41>
    星月
  </h3> <div class="num" data-v-1fad0c41><div data-v-1fad0c41><h3 data-v-1fad0c41>82</h3> <h6 data-v-1fad0c41>Articles</h6></div> <div data-v-1fad0c41><h3 data-v-1fad0c41>9</h3> <h6 data-v-1fad0c41>Tags</h6></div></div> <ul class="social-links" data-v-1fad0c41></ul> <hr data-v-1fad0c41></div> <nav class="nav-links"><div class="nav-item"><a href="/" class="nav-link"><i class="iconfont reco-home"></i>
  首页
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-category"></i>
      博客
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="/categories/ES6模块化与异步编程/" class="nav-link"><i class="undefined"></i>
  ES6模块化与异步编程
</a></li><li class="dropdown-item"><!----> <a href="/categories/css/" class="nav-link"><i class="undefined"></i>
  css
</a></li><li class="dropdown-item"><!----> <a href="/categories/TypeScript/" class="nav-link"><i class="undefined"></i>
  TypeScript
</a></li><li class="dropdown-item"><!----> <a href="/categories/html/" class="nav-link"><i class="undefined"></i>
  html
</a></li><li class="dropdown-item"><!----> <a href="/categories/JavaScript/" class="nav-link"><i class="undefined"></i>
  JavaScript
</a></li><li class="dropdown-item"><!----> <a href="/categories/Node.js/" class="nav-link"><i class="undefined"></i>
  Node.js
</a></li><li class="dropdown-item"><!----> <a href="/categories/Vue2/" class="nav-link"><i class="undefined"></i>
  Vue2
</a></li><li class="dropdown-item"><!----> <a href="/categories/Vue3/" class="nav-link"><i class="undefined"></i>
  Vue3
</a></li><li class="dropdown-item"><!----> <a href="/categories/webpack/" class="nav-link"><i class="undefined"></i>
  webpack
</a></li></ul></div></div><div class="nav-item"><a href="/tag/" class="nav-link"><i class="iconfont reco-tag"></i>
  标签
</a></div><div class="nav-item"><a href="/timeline/" class="nav-link"><i class="iconfont reco-date"></i>
  时间线
</a></div><div class="nav-item"><a href="/docs/theme-reco/" class="nav-link"><i class="iconfont reco-message"></i>
  随记
</a></div><div class="nav-item"><div class="dropdown-wrapper"><a class="dropdown-title"><span class="title"><i class="iconfont reco-message"></i>
      联系方式
    </span> <span class="arrow right"></span></a> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://github.com/858399075" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-github"></i>
  GitHub
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://gitee.com/xingyueqianduan" target="_blank" rel="noopener noreferrer" class="nav-link external"><i class="iconfont reco-github"></i>
  Gitee
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://blog.yhxweb.top/" target="_blank" rel="noopener noreferrer" class="nav-link external"><i></i>
  QQ:76120220
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://blog.yhxweb.top/" target="_blank" rel="noopener noreferrer" class="nav-link external"><i></i>
  WX:15237156071
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav> <!----> </aside> <div class="password-shadow password-wrapper-in" style="display:none;" data-v-59e6cb88 data-v-5bb33761><h3 class="title" data-v-59e6cb88>TypeScript入门111</h3> <!----> <label id="box" class="inputBox" data-v-59e6cb88><input type="password" value="" data-v-59e6cb88> <span data-v-59e6cb88>Konck! Knock!</span> <button data-v-59e6cb88>OK</button></label> <div class="footer" data-v-59e6cb88><span data-v-59e6cb88><i class="iconfont reco-theme" data-v-59e6cb88></i> <a target="blank" href="https://vuepress-theme-reco.recoluan.com" data-v-59e6cb88>vuePress-theme-reco</a></span> <span data-v-59e6cb88><i class="iconfont reco-copyright" data-v-59e6cb88></i> <a data-v-59e6cb88><span data-v-59e6cb88>星月</span>
          
        <!---->
        2022
      </a></span></div></div> <div data-v-5bb33761><div data-v-5bb33761><main class="page"><section style="display:;"><div class="page-title"><h1 class="title">TypeScript入门111</h1> <div data-v-8a445198><i class="iconfont reco-account" data-v-8a445198><span data-v-8a445198>星月</span></i> <i class="iconfont reco-date" data-v-8a445198><span data-v-8a445198>10/2/2022</span></i> <!----> <i class="tags iconfont reco-tag" data-v-8a445198><span class="tag-item" data-v-8a445198>TypeScript</span></i></div></div> <div class="theme-reco-content content__default"><h1 id="typescript-入门"><a href="#typescript-入门" class="header-anchor">#</a> TypeScript 入门</h1> <h1 id="_1-typescript-介绍"><a href="#_1-typescript-介绍" class="header-anchor">#</a> <strong>1. TypeScript 介绍</strong></h1> <h2 id="_1-1-typescript-是什么"><a href="#_1-1-typescript-是什么" class="header-anchor">#</a> <strong>1.1 TypeScript 是什么</strong></h2> <blockquote><p><strong>T</strong>ype<strong>S</strong>cript（简称：TS）是 JavaScript 的超集（JS 有的 TS 都有）。</p> <p>TypeScript = Type + JavaScript（在 JS 基础之上，为 JS 添加了类型支持）。</p> <p>TypeScript 是微软开发的开源编程语言，可以在任何运行 JavaScript 的地方运行。</p></blockquote> <h2 id="_1-2-typescript-为什么要为-js-添加类型支持"><a href="#_1-2-typescript-为什么要为-js-添加类型支持" class="header-anchor">#</a> <strong>1.2 TypeScript 为什么要为 JS 添加类型支持？</strong></h2> <p><code>背景</code>：JS 的类型系统存在“先天缺陷”，JS 代码中绝大部分错误都是类型错误（Uncaught TypeError）。</p> <p><code>问题</code>：增加了找 Bug、改 Bug 的时间，严重影响开发效率。</p> <p>从编程语言的动静来区分，TypeScript 属于静态类型的编程语言，JS 属于动态类型的编程语言。</p> <p>静态类型：编译期做类型检查； 动态类型：执行期做类型检查。</p> <p>代码编译和代码执行的顺序：1 编译 2 执行。</p> <p>对于 JS 来说：需要等到代码真正去执行的时候才能发现错误（晚）。</p> <p>对于 TS 来说：在代码编译的时候（代码执行前）就可以发现错误（早）。</p> <p>并且，配合 VSCode 等开发工具，TS 可以<code>提前到在编写代码的同时</code>就发现代码中的错误，<code>减少找 Bug、改 Bug 时间</code>。</p> <h2 id="_1-3-typescript-相比-js-的优势"><a href="#_1-3-typescript-相比-js-的优势" class="header-anchor">#</a> <strong>1.3 TypeScript 相比 JS 的优势</strong></h2> <ol><li><p>更早（写代码的同时）发现错误，减少找 Bug、改 Bug 时间，提升开发效率。</p></li> <li><p>程序中任何位置的代码都有代码提示，随时随地的安全感，增强了开发体验。</p></li> <li><p>强大的类型系统提升了代码的可维护性，使得重构代码更加容易。</p></li> <li><p>支持最新的 ECMAScript 语法，优先体验最新的语法，让你走在前端技术的最前沿。</p></li> <li><p>TS 类型推断机制，不需要在代码中的每个地方都显示标注类型，让你在享受优势的同时，尽量降低了成本。</p> <p><strong>除此之外，Vue 3 源码使用 TS 重写、Angular 默认支持 TS、React 与 TS 完美配合，TypeScript 已成为大中型前端项目的首先编程语言。</strong></p></li></ol> <h1 id="_2-typescript-初体验"><a href="#_2-typescript-初体验" class="header-anchor">#</a> <strong>2. TypeScript 初体验</strong></h1> <h2 id="_2-1-安装编译-ts-的工具包"><a href="#_2-1-安装编译-ts-的工具包" class="header-anchor">#</a> <strong>2.1 安装编译 TS 的工具包</strong></h2> <p>问题：为什么要安装编译 TS 的工具包？</p> <p>回答：Node.js/浏览器，只认识 JS 代码，不认识 TS 代码。需要先将 TS 代码转化为 JS 代码，然后才能运行。</p> <p>安装命令：<code>npm i -g typescrip</code>t。</p> <p>typescript 包：用来编译 TS 代码的包，提供了 tsc 命令，实现了 TS -&gt; JS 的转化。</p> <p>验证是否安装成功：<code>tsc –v（查看 typescript 的版本）</code></p> <p><img src="https://img-blog.csdnimg.cn/bb735f77a267480b981abdcc2c855fd5.png" alt="在这里插入图片描述"></p> <h2 id="_2-2-编译并运行-ts-代码"><a href="#_2-2-编译并运行-ts-代码" class="header-anchor">#</a> <strong>2.2 编译并运行 TS 代码</strong></h2> <ol><li><p>创建 hello.ts 文件（注意：TS 文件的后缀名为 .ts）。</p></li> <li><p>将 TS 编译为 JS：在终端中输入命令，tsc hello.ts（此时，在同级目录中会出现一个同名的 JS 文件）。</p></li> <li><p>执行 JS 代码：在终端中输入命令，node hello.js。</p></li></ol> <p><img src="https://img-blog.csdnimg.cn/8148f949405e44ae95e93a50be298542.png" alt="在这里插入图片描述"></p> <p>说明：所有合法的 JS 代码都是 TS 代码，有 JS 基础只需要学习 TS 的类型即可。</p> <p>注意：由 TS 编译生成的 JS 文件，代码中就没有类型信息了。</p> <h2 id="_2-3-简化运行-ts-的步骤"><a href="#_2-3-简化运行-ts-的步骤" class="header-anchor">#</a> <strong>2.3 简化运行 TS 的步骤</strong></h2> <p>问题描述：每次修改代码后，都要<strong>重复执行</strong>两个命令，才能运行 TS 代码，太繁琐。</p> <p>简化方式：使用 ts-node 包，直接在 Node.js 中执行 TS 代码。</p> <p>安装命令：<code>npm i -g ts-node</code>（ts-node 包提供了 ts-node 命令）。</p> <p>使用方式：<code>ts-node hello.ts</code>。</p> <p>解释：ts-node 命令在内部偷偷的将 TS -&gt; JS，然后，再运行 JS 代码。</p> <h1 id="_3-typescript-常用类型"><a href="#_3-typescript-常用类型" class="header-anchor">#</a> <strong>3.TypeScript 常用类型</strong></h1> <h3 id="概述"><a href="#概述" class="header-anchor">#</a> <strong>概述</strong></h3> <p>TypeScript 是 JS 的超集，TS 提供了 JS 的所有功能，并且额外的增加了：类型系统。</p> <ul><li><p>所有的 JS 代码都是 TS 代码。</p></li> <li><p>JS 有类型（比如，number/string 等），但是 JS 不会检查变量的类型是否发生变化。而 TS 会检查。</p></li></ul> <p>TypeScript 类型系统的主要优势：<code>可以显示标记出代码中的意外行为，从而降低了发生错误的可能性</code>。</p> <ol><li><p>类型注解</p></li> <li><p>常用基础类型</p></li></ol> <h3 id="_3-1-类型注解"><a href="#_3-1-类型注解" class="header-anchor">#</a> <strong>3.1 类型注解</strong></h3> <p>示例代码：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">let</span> age<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=</span> <span class="token number">13</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>说明：代码中的 <code>: number</code> 就是类型注解。</p> <p>作用：为变量添加类型约束。比如，上述代码中，约定变量 age 的类型为 number（数值类型）。</p> <p>解释：<code>约定了什么类型，就只能给变量赋值该类型的值</code>，否则，就会报错。</p> <p><img src="https://img-blog.csdnimg.cn/a282244d4c764a4481013682e53a528c.png" alt="在这里插入图片描述"></p> <h3 id="_3-2-常用基础类型概述"><a href="#_3-2-常用基础类型概述" class="header-anchor">#</a> <strong>3.2 常用基础类型概述</strong></h3> <p>可以将 TS 中的常用基础类型细分为两类：1、 JS 已有类型， 2 、TS 新增类型。</p> <ol><li>JS 已有类型</li></ol> <ul><li><p>原始类型：number/string/boolean/null/undefined/symbol。</p></li> <li><p>对象类型：object（包括，数组、对象、函数等对象）。</p></li></ul> <p>2.TS 新增类型</p> <ul><li>联合类型、自定义类型（类型别名）、接口、元组、字面量类型、枚举、void、any 等。</li></ul> <h3 id="_3-3-原始类型"><a href="#_3-3-原始类型" class="header-anchor">#</a> <strong>3.3 原始类型</strong></h3> <ol><li>原始类型：number/string/boolean/null/undefined/symbol。</li></ol> <p>特点：<code>简单</code>。这些类型，完全按照 JS 中类型的名称来书写。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">let</span> age<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=</span> <span class="token number">13</span>

<span class="token keyword">let</span> myName<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">=</span> <span class="token string">'星月'</span>

<span class="token keyword">let</span> isLoading<span class="token operator">:</span> <span class="token builtin">boolean</span> <span class="token operator">=</span> <span class="token boolean">false</span>

<span class="token keyword">let</span> a<span class="token operator">:</span> <span class="token keyword">null</span> <span class="token operator">=</span> <span class="token keyword">null</span>

<span class="token keyword">let</span> b<span class="token operator">:</span> <span class="token keyword">undefined</span> <span class="token operator">=</span> <span class="token keyword">undefined</span>

<span class="token keyword">let</span> s<span class="token operator">:</span> <span class="token builtin">symbol</span> <span class="token operator">=</span> <span class="token function">Symbol</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><h3 id="_3-4-数组类型"><a href="#_3-4-数组类型" class="header-anchor">#</a> <strong>3.4 数组类型</strong></h3> <ol start="2"><li>对象类型：object（包括，数组、对象、函数等对象）。</li></ol> <p>特点：对象类型，在 TS 中更加细化，<strong>每个具体的对象都有自己的类型语法</strong>。</p> <p>数组类型的两种写法：（<strong>推荐使用</strong> <strong>number[]</strong> <strong>写法</strong>）</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 数组类型：</span>

<span class="token keyword">let</span> numbers<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span>  <span class="token comment">// 推荐使用</span>

<span class="token keyword">let</span> numbers1<span class="token operator">:</span> <span class="token builtin">Array</span><span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">&gt;</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p>需求：数组中既有 number 类型，又有 string 类型，这个数组的类型应该如何写？</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 联合类型：</span>
<span class="token comment">// 添加小括号，表示：首先是数组，然后，这个数组中能够出现 number 或 string 类型的元素</span>
<span class="token keyword">let</span> arr<span class="token operator">:</span> <span class="token punctuation">(</span><span class="token builtin">number</span> <span class="token operator">|</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">]</span>

<span class="token comment">// 不添加小括号，表示：arr1 既可以是 number 类型，又可以是 string[]</span>
<span class="token keyword">let</span> arr1<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">|</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">]</span>
<span class="token keyword">let</span> arr1<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">|</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">123</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>解释：<code>|</code>（竖线）在 TS 中叫做联合类型（由两个或多个其他类型组成的类型，表示可以是这些类型中的任意一种）。</p> <p>注意：这是 TS 中联合类型的语法，只有一根竖线，不要与 JS 中的或（||）混淆了。</p> <h3 id="_3-5-类型别名"><a href="#_3-5-类型别名" class="header-anchor">#</a> <strong>3.5 类型别名</strong></h3> <p>类型别名（自定义类型）：为任意类型起别名。</p> <p>使用场景：当同一类型（复杂）被多次使用时，可以通过类型别名，简化该类型的使用。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// let arr: (number | string)[] = [1, 3, 5, 'a', 'b']</span>
<span class="token comment">// let arr1: (number | string)[] = [1, 'x', 2, 'y']</span>

<span class="token comment">// 改造：</span>

<span class="token comment">// 类型别名：</span>
<span class="token keyword">type</span> <span class="token class-name">CustomArray</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token builtin">number</span> <span class="token operator">|</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token punctuation">]</span>

<span class="token keyword">let</span> arr<span class="token operator">:</span> CustomArray <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token string">'b'</span><span class="token punctuation">]</span>
<span class="token keyword">let</span> arr1<span class="token operator">:</span> CustomArray <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token string">'x'</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token string">'y'</span><span class="token punctuation">]</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><p>解释：</p> <ol><li><p>使用 type 关键字来创建类型别名。</p></li> <li><p>类型别名（比如，此处的 CustomArray），可以是任意合法的变量名称。</p></li> <li><p>创建类型别名后，直接<code>使用该类型别名作为变量的类型注解</code>即可。</p></li></ol> <h3 id="_3-6-函数类型"><a href="#_3-6-函数类型" class="header-anchor">#</a> <strong>3.6 函数类型</strong></h3> <p>函数的类型实际上指的是：函数参数和返回值的类型。</p> <p>为函数指定类型的两种方式：1 单独指定参数、返回值的类型 2 同时指定参数、返回值的类型。</p> <ol><li>单独指定参数、返回值的类</li></ol> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 1. 单独指定参数、返回值类型：</span>

<span class="token keyword">function</span> <span class="token function">add</span><span class="token punctuation">(</span>num1<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> num2<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">{</span>
   <span class="token keyword">return</span> num1 <span class="token operator">+</span> num2
<span class="token punctuation">}</span>

<span class="token keyword">const</span> add <span class="token operator">=</span> <span class="token punctuation">(</span>num1<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> num2<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
   <span class="token keyword">return</span> num1 <span class="token operator">+</span> num2
<span class="token punctuation">}</span>

<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span>

<span class="token comment">// ---</span>

<span class="token comment">// 2. 同时指定参数、返回值类型：</span>
<span class="token keyword">const</span> <span class="token function-variable function">add</span><span class="token operator">:</span> <span class="token punctuation">(</span>num1<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> num2<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token function-variable function">number</span> <span class="token operator">=</span> <span class="token punctuation">(</span>num1<span class="token punctuation">,</span> num2<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> num1 <span class="token operator">+</span> num2
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><p><code>函数的类型实际上指的是：函数参数和返回值的类型。</code></p> <p><strong>为函数指定类型的两种方式</strong>：1 单独指定参数、返回值的类型 2 同时指定参数、返回值的类型。</p> <ol start="2"><li><p>同时指定参数、返回值的类型：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 2. 同时指定参数、返回值类型：</span>
<span class="token keyword">const</span> <span class="token function-variable function">add</span><span class="token operator">:</span> <span class="token punctuation">(</span>num1<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> num2<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token function-variable function">number</span> <span class="token operator">=</span> <span class="token punctuation">(</span>num1<span class="token punctuation">,</span> num2<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> num1 <span class="token operator">+</span> num2
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div></li></ol> <p>解释：当函数作为表达式时，可以通过<code>类似箭头函数形式的语法</code>来为函数添加类型。</p> <p>注意：这种形式只适用于函数表达式。</p> <p><strong>如果函数没有返回值，那么，函数返回值类型为：<code>void</code>。</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">function</span> <span class="token function">greet</span><span class="token punctuation">(</span>name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
  <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Hello'</span><span class="token punctuation">,</span> name<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token function">greet</span><span class="token punctuation">(</span><span class="token string">'xingyue'</span><span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br></div></div><p><strong>使用函数实现某个功能时，参数可以传<code>也可以不传</code>。</strong></p> <p>这种情况下，在给函数参数指定类型时，就用到可选参数了。</p> <p>比如，数组的 slice 方法，可以 slice() 也可以 slice(1) 还可以 slice(1, 3)。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">function</span> <span class="token function">mySlice</span><span class="token punctuation">(</span>start<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> end<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">{</span>
  <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'起始索引：'</span><span class="token punctuation">,</span> start<span class="token punctuation">,</span> <span class="token string">'结束索引：'</span><span class="token punctuation">,</span> end<span class="token punctuation">)</span>
<span class="token punctuation">}</span>

<span class="token function">mySlice</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span>
<span class="token function">mySlice</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span>
<span class="token function">mySlice</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><p>可选参数：在可传可不传的参数名称后面添加<code>?</code>（问号）。</p> <p>注意：<code>可选参数只能出现在参数列表的最后</code>，也就是说可选参数后面不能再出现必选参数。</p> <h3 id="_3-7-对象类型"><a href="#_3-7-对象类型" class="header-anchor">#</a> <strong>3.7 对象类型</strong></h3> <p>JS 中的对象是由属性和方法构成的，而 TS 中对象的类型就是在描述对象的结构（有什么类型的属性和方法）。</p> <p>对象类型的写法：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">let</span> person<span class="token operator">:</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> age<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> <span class="token function">sayHi</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span> <span class="token function">greet</span><span class="token punctuation">(</span>name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span> <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'星月'</span><span class="token punctuation">,</span>
  age<span class="token operator">:</span> <span class="token number">18</span><span class="token punctuation">,</span>
  <span class="token function">sayHi</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">greet</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">let</span> person<span class="token operator">:</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span>
  age<span class="token operator">:</span> <span class="token builtin">number</span>
  <span class="token comment">// sayHi(): void</span>
  <span class="token function-variable function">sayHi</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">void</span>
  <span class="token function">greet</span><span class="token punctuation">(</span>name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span>
<span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'刘老师'</span><span class="token punctuation">,</span>
  age<span class="token operator">:</span> <span class="token number">18</span><span class="token punctuation">,</span>
  <span class="token function">sayHi</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">greet</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p>解释：</p> <ol><li><p>直接使用 {} 来描述对象结构。属性采用属性名: 类型的形式；方法采用方法名(): 返回值类型的形式。</p></li> <li><p>如果方法有参数，就在方法名后面的小括号中指定参数类型（比如：greet(name: string): void）。</p></li> <li><p>在一行代码中指定对象的多个属性类型时，使用 ;（分号）来分隔。</p></li></ol> <ul><li><p>如果一行代码只指定一个属性类型（通过换行来分隔多个属性类型），可以去掉 ;（分号）。</p></li> <li><p>方法的类型也可以使用箭头函数形式（比如：{ sayHi: () =&gt; void }）。</p></li></ul> <p><strong>对象的属性或方法，也可以是可选的，此时就用到可选属性了。</strong></p> <p>比如，我们在使用 axios({ … }) 时，如果发送 GET 请求，method 属性就可以省略。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">function</span> <span class="token function">myAxios</span><span class="token punctuation">(</span>config<span class="token operator">:</span> <span class="token punctuation">{</span> url<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> method<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token function">myAxios</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
  url<span class="token operator">:</span> <span class="token string">''</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br></div></div><p><code>可选属性</code>的语法与函数可选参数的语法一致，都使用 ?（问号）来表示。</p> <h3 id="_3-8-接口"><a href="#_3-8-接口" class="header-anchor">#</a> <strong>3.8 接口</strong></h3> <p>当一个对象类型被多次使用时，一般会使用接口（<code>interface</code>）来描述对象的类型，达到复用的目的。</p> <p>解释：</p> <ol><li><p>使用 interface 关键字来声明接口。</p></li> <li><p>接口名称（比如，此处的 IPerson），可以是任意合法的变量名称。</p></li> <li><p>声明接口后，直接使用接口名称作为变量的类型。</p></li> <li><p>因为每一行只有一个属性类型，因此，属性类型后没有 ;（分号）</p></li></ol> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// let person: { name: string; age: number; sayHi(): void } = {</span>
<span class="token comment">//   name: '星月',</span>
<span class="token comment">//   age: 18,</span>
<span class="token comment">//   sayHi() {}</span>
<span class="token comment">// }</span>

<span class="token comment">// let person1: { name: string; age: number; sayHi(): void }</span>

<span class="token comment">// 接口：</span>
<span class="token keyword">interface</span> <span class="token class-name">IPerson</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span>
  age<span class="token operator">:</span> <span class="token builtin">number</span>
  <span class="token function">sayHi</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> person<span class="token operator">:</span> IPerson <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'星月'</span><span class="token punctuation">,</span>
  age<span class="token operator">:</span> <span class="token number">13</span><span class="token punctuation">,</span>
  <span class="token function">sayHi</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> person1<span class="token operator">:</span> IPerson <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'xingyue'</span><span class="token punctuation">,</span>
  age<span class="token operator">:</span> <span class="token number">14</span><span class="token punctuation">,</span>
  <span class="token function">sayHi</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><p><strong>interface（接口）和 type（类型别名）的对比：</strong></p> <ul><li><p>相同点：都可以给对象指定类型。</p></li> <li><p>不同点：</p> <ul><li><p>接口，只能为对象指定类型。</p></li> <li><p>类型别名，不仅可以为对象指定类型，实际上可以为任意类型指定别名。</p></li></ul></li></ul> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 接口：</span>
<span class="token comment">// interface IPerson {</span>
<span class="token comment">//   name: string</span>
<span class="token comment">//   age: number</span>
<span class="token comment">//   sayHi(): void</span>
<span class="token comment">// }</span>

<span class="token comment">// 类型别名</span>
<span class="token keyword">type</span> <span class="token class-name">IPerson</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span>
  age<span class="token operator">:</span> <span class="token builtin">number</span>
  <span class="token function">sayHi</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> person<span class="token operator">:</span> IPerson <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'星月'</span><span class="token punctuation">,</span>
  age<span class="token operator">:</span> <span class="token number">18</span><span class="token punctuation">,</span>
  <span class="token function">sayHi</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br></div></div><p><strong>如果两个接口之间有相同的属性或方法，可以将公共的属性或方法抽离出来，通过继承来实现复用。</strong></p> <p>比如，这两个接口都有 x、y 两个属性，重复写两次，可以，但很繁琐</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">Point2D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>
<span class="token comment">// interface Point3D { x: number; y: number; z: number }</span>

<span class="token comment">// 使用 继承 实现复用：</span>
<span class="token keyword">interface</span> <span class="token class-name">Point3D</span> <span class="token keyword">extends</span> <span class="token class-name">Point2D</span> <span class="token punctuation">{</span>
  z<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> p3<span class="token operator">:</span> Point3D <span class="token operator">=</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
  y<span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
  z<span class="token operator">:</span> <span class="token number">0</span>
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><p>解释：</p> <ol><li><p>使用<code>extends</code>（继承）关键字实现了接口 Point3D 继承 Point2D。</p></li> <li><p>继承后，Point3D 就有了 Point2D 的所有属性和方法（此时，Point3D 同时有 x、y、z 三个属性）。</p></li></ol> <h3 id="_3-9-元组"><a href="#_3-9-元组" class="header-anchor">#</a> <strong>3.9 元组</strong></h3> <p>场景：在地图中，使用经纬度坐标来标记位置信息。</p> <p>可以使用数组来记录坐标，那么，该数组中只有两个元素，并且这两个元素都是数值类型。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">let</span> position<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">39</span><span class="token punctuation">,</span> <span class="token number">114</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">]</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>使用 number[] 的缺点：不严谨，因为该类型的数组中可以出现任意多个数字。</p> <p>更好的方式：元组（Tuple）。</p> <p>元组类型是另一种类型的数组，它确切地知道包含多少个元素，以及特定索引对应的类型。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 使用 元组 ：</span>
<span class="token keyword">let</span> position<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token builtin">number</span><span class="token punctuation">,</span> <span class="token builtin">string</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">39</span><span class="token punctuation">,</span> <span class="token string">'114'</span><span class="token punctuation">]</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br></div></div><p>解释：</p> <ol><li><p>元组类型可以确切地标记出有多少个元素，以及每个元素的类型。</p></li> <li><p>该示例中，元素有两个元素，每个元素的类型都是 number。</p></li></ol> <h3 id="_3-10-类型推论"><a href="#_3-10-类型推论" class="header-anchor">#</a> <strong>3.10 类型推论</strong></h3> <p>在 TS 中，某些没有明确指出类型的地方，TS 的类型推论机制会帮助提供类型。</p> <p>换句话说：由于类型推论的存在，这些地方，类型注解可以省略不写！</p> <p>发生类型推论的 2 种常见场景：1 声明变量并初始化时  2 决定函数返回值时。</p> <p><img src="https://img-blog.csdnimg.cn/69960bbfcc3c4f0aa77e5afc9ef11622.png" alt="在这里插入图片描述"></p> <p>注意：这两种情况下，类型注解可以省略不写！</p> <p>推荐：<code>能省略类型注解的地方就省略</code>（偷懒，充分利用TS类型推论的能力，提升开发效率）。</p> <p>技巧：如果不知道类型，可以通过鼠标放在变量名称上，利用 VSCode 的提示来查看类型。</p> <h3 id="_3-11-类型断言"><a href="#_3-11-类型断言" class="header-anchor">#</a> <strong>3.11 类型断言</strong></h3> <p>有时候你会比 TS 更加明确一个值的类型，此时，可以使用类型断言来指定更具体的类型。</p> <p>比如，</p> <div class="language-html line-numbers-mode"><pre class="language-html"><code><span class="token doctype"><span class="token punctuation">&lt;!</span><span class="token doctype-tag">DOCTYPE</span> <span class="token name">html</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>html</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>en<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">charset</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>UTF-8<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">http-equiv</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>X-UA-Compatible<span class="token punctuation">&quot;</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>IE=edge<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>meta</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>viewport<span class="token punctuation">&quot;</span></span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>width=device-width, initial-scale=1.0<span class="token punctuation">&quot;</span></span> <span class="token punctuation">/&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>title</span><span class="token punctuation">&gt;</span></span>Document<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>title</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">&gt;</span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>http://www.yhxweb.top/<span class="token punctuation">&quot;</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">&quot;</span>link<span class="token punctuation">&quot;</span></span><span class="token punctuation">&gt;</span></span>星月前端博客<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">&gt;</span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">&gt;</span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>html</span><span class="token punctuation">&gt;</span></span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">const</span> aLink <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'link'</span><span class="token punctuation">)</span> <span class="token keyword">as</span> HTMLAnchorElement
<span class="token comment">// const aLink = &lt;HTMLAnchorElement&gt;document.getElementById('link')</span>
aLink<span class="token punctuation">.</span>href
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p><strong>注意</strong>：getElementById 方法返回值的类型是 HTMLElement，该类型只包含所有标签公共的属性或方法，不包含 a 标签特有的 href 等属性。</p> <p>因此，这个<strong>类型太宽泛（不具体）</strong>，无法操作 href 等 a 标签特有的属性或方法。</p> <p><strong>解决方式</strong>：这种情况下就需要<code>使用类型断言指定更加具体的类型</code>。</p> <p><img src="https://img-blog.csdnimg.cn/9f0bd5844725408b834dd4e9bc55dc01.png" alt="在这里插入图片描述"></p> <p>解释：</p> <ol><li><p>使用 as 关键字实现类型断言。</p></li> <li><p>关键字 as 后面的类型是一个更加具体的类型（HTMLAnchorElement 是 HTMLElement 的子类型）。</p></li> <li><p>通过类型断言，aLink 的类型变得更加具体，这样就可以访问 a 标签特有的属性或方法了。</p></li></ol> <p>另一种语法，使用 &lt;&gt; 语法，这种语法形式不常用知道即可：</p> <p><strong>技巧：在浏览器控制台，通过<code>console.dir() 打印 DOM 元素</code>，在属性列表的最后面，即可看到该元素的类型。</strong></p> <p><strong>常见的具体类型如下：</strong></p> <p>一般均为HTMLElement，特殊的为HTML+标签名+Element ，当然也有些标签名为单字母的例如h1-h6，他们的类型为HTMLHeadingElement。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code>	<span class="token string-property property">&quot;a&quot;</span><span class="token operator">:</span> HTMLAnchorElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;abbr&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;address&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;applet&quot;</span><span class="token operator">:</span> HTMLAppletElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;area&quot;</span><span class="token operator">:</span> HTMLAreaElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;article&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;aside&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;audio&quot;</span><span class="token operator">:</span> HTMLAudioElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;b&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;base&quot;</span><span class="token operator">:</span> HTMLBaseElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;bdi&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;bdo&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;blockquote&quot;</span><span class="token operator">:</span> HTMLQuoteElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;body&quot;</span><span class="token operator">:</span> HTMLBodyElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;br&quot;</span><span class="token operator">:</span> HTMLBRElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;button&quot;</span><span class="token operator">:</span> HTMLButtonElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;canvas&quot;</span><span class="token operator">:</span> HTMLCanvasElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;caption&quot;</span><span class="token operator">:</span> HTMLTableCaptionElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;cite&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;code&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;col&quot;</span><span class="token operator">:</span> HTMLTableColElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;colgroup&quot;</span><span class="token operator">:</span> HTMLTableColElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;data&quot;</span><span class="token operator">:</span> HTMLDataElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;datalist&quot;</span><span class="token operator">:</span> HTMLDataListElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;dd&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;del&quot;</span><span class="token operator">:</span> HTMLModElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;details&quot;</span><span class="token operator">:</span> HTMLDetailsElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;dfn&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;dialog&quot;</span><span class="token operator">:</span> HTMLDialogElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;dir&quot;</span><span class="token operator">:</span> HTMLDirectoryElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;div&quot;</span><span class="token operator">:</span> HTMLDivElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;dl&quot;</span><span class="token operator">:</span> HTMLDListElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;dt&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;em&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;embed&quot;</span><span class="token operator">:</span> HTMLEmbedElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;fieldset&quot;</span><span class="token operator">:</span> HTMLFieldSetElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;figcaption&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;figure&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;font&quot;</span><span class="token operator">:</span> HTMLFontElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;footer&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;form&quot;</span><span class="token operator">:</span> HTMLFormElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;frame&quot;</span><span class="token operator">:</span> HTMLFrameElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;frameset&quot;</span><span class="token operator">:</span> HTMLFrameSetElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;h1&quot;</span><span class="token operator">:</span> HTMLHeadingElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;h2&quot;</span><span class="token operator">:</span> HTMLHeadingElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;h3&quot;</span><span class="token operator">:</span> HTMLHeadingElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;h4&quot;</span><span class="token operator">:</span> HTMLHeadingElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;h5&quot;</span><span class="token operator">:</span> HTMLHeadingElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;h6&quot;</span><span class="token operator">:</span> HTMLHeadingElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;head&quot;</span><span class="token operator">:</span> HTMLHeadElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;header&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;hgroup&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;hr&quot;</span><span class="token operator">:</span> HTMLHRElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;html&quot;</span><span class="token operator">:</span> HTMLHtmlElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;i&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;iframe&quot;</span><span class="token operator">:</span> HTMLIFrameElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;img&quot;</span><span class="token operator">:</span> HTMLImageElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;input&quot;</span><span class="token operator">:</span> HTMLInputElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;ins&quot;</span><span class="token operator">:</span> HTMLModElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;kbd&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;label&quot;</span><span class="token operator">:</span> HTMLLabelElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;legend&quot;</span><span class="token operator">:</span> HTMLLegendElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;li&quot;</span><span class="token operator">:</span> HTMLLIElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;link&quot;</span><span class="token operator">:</span> HTMLLinkElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;main&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;map&quot;</span><span class="token operator">:</span> HTMLMapElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;mark&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;marquee&quot;</span><span class="token operator">:</span> HTMLMarqueeElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;menu&quot;</span><span class="token operator">:</span> HTMLMenuElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;meta&quot;</span><span class="token operator">:</span> HTMLMetaElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;meter&quot;</span><span class="token operator">:</span> HTMLMeterElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;nav&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;noscript&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;object&quot;</span><span class="token operator">:</span> HTMLObjectElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;ol&quot;</span><span class="token operator">:</span> HTMLOListElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;optgroup&quot;</span><span class="token operator">:</span> HTMLOptGroupElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;option&quot;</span><span class="token operator">:</span> HTMLOptionElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;output&quot;</span><span class="token operator">:</span> HTMLOutputElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;p&quot;</span><span class="token operator">:</span> HTMLParagraphElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;param&quot;</span><span class="token operator">:</span> HTMLParamElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;picture&quot;</span><span class="token operator">:</span> HTMLPictureElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;pre&quot;</span><span class="token operator">:</span> HTMLPreElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;progress&quot;</span><span class="token operator">:</span> HTMLProgressElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;q&quot;</span><span class="token operator">:</span> HTMLQuoteElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;rp&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;rt&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;ruby&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;s&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;samp&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;script&quot;</span><span class="token operator">:</span> HTMLScriptElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;section&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;select&quot;</span><span class="token operator">:</span> HTMLSelectElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;slot&quot;</span><span class="token operator">:</span> HTMLSlotElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;small&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;source&quot;</span><span class="token operator">:</span> HTMLSourceElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;span&quot;</span><span class="token operator">:</span> HTMLSpanElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;strong&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;style&quot;</span><span class="token operator">:</span> HTMLStyleElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;sub&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;summary&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;sup&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;table&quot;</span><span class="token operator">:</span> HTMLTableElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;tbody&quot;</span><span class="token operator">:</span> HTMLTableSectionElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;td&quot;</span><span class="token operator">:</span> HTMLTableDataCellElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;template&quot;</span><span class="token operator">:</span> HTMLTemplateElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;textarea&quot;</span><span class="token operator">:</span> HTMLTextAreaElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;tfoot&quot;</span><span class="token operator">:</span> HTMLTableSectionElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;th&quot;</span><span class="token operator">:</span> HTMLTableHeaderCellElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;thead&quot;</span><span class="token operator">:</span> HTMLTableSectionElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;time&quot;</span><span class="token operator">:</span> HTMLTimeElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;title&quot;</span><span class="token operator">:</span> HTMLTitleElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;tr&quot;</span><span class="token operator">:</span> HTMLTableRowElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;track&quot;</span><span class="token operator">:</span> HTMLTrackElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;u&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;ul&quot;</span><span class="token operator">:</span> HTMLUListElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;var&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;video&quot;</span><span class="token operator">:</span> HTMLVideoElement<span class="token punctuation">;</span>
    <span class="token string-property property">&quot;wbr&quot;</span><span class="token operator">:</span> HTMLElement<span class="token punctuation">;</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br><span class="line-number">42</span><br><span class="line-number">43</span><br><span class="line-number">44</span><br><span class="line-number">45</span><br><span class="line-number">46</span><br><span class="line-number">47</span><br><span class="line-number">48</span><br><span class="line-number">49</span><br><span class="line-number">50</span><br><span class="line-number">51</span><br><span class="line-number">52</span><br><span class="line-number">53</span><br><span class="line-number">54</span><br><span class="line-number">55</span><br><span class="line-number">56</span><br><span class="line-number">57</span><br><span class="line-number">58</span><br><span class="line-number">59</span><br><span class="line-number">60</span><br><span class="line-number">61</span><br><span class="line-number">62</span><br><span class="line-number">63</span><br><span class="line-number">64</span><br><span class="line-number">65</span><br><span class="line-number">66</span><br><span class="line-number">67</span><br><span class="line-number">68</span><br><span class="line-number">69</span><br><span class="line-number">70</span><br><span class="line-number">71</span><br><span class="line-number">72</span><br><span class="line-number">73</span><br><span class="line-number">74</span><br><span class="line-number">75</span><br><span class="line-number">76</span><br><span class="line-number">77</span><br><span class="line-number">78</span><br><span class="line-number">79</span><br><span class="line-number">80</span><br><span class="line-number">81</span><br><span class="line-number">82</span><br><span class="line-number">83</span><br><span class="line-number">84</span><br><span class="line-number">85</span><br><span class="line-number">86</span><br><span class="line-number">87</span><br><span class="line-number">88</span><br><span class="line-number">89</span><br><span class="line-number">90</span><br><span class="line-number">91</span><br><span class="line-number">92</span><br><span class="line-number">93</span><br><span class="line-number">94</span><br><span class="line-number">95</span><br><span class="line-number">96</span><br><span class="line-number">97</span><br><span class="line-number">98</span><br><span class="line-number">99</span><br><span class="line-number">100</span><br><span class="line-number">101</span><br><span class="line-number">102</span><br><span class="line-number">103</span><br><span class="line-number">104</span><br><span class="line-number">105</span><br><span class="line-number">106</span><br><span class="line-number">107</span><br><span class="line-number">108</span><br><span class="line-number">109</span><br><span class="line-number">110</span><br><span class="line-number">111</span><br><span class="line-number">112</span><br><span class="line-number">113</span><br><span class="line-number">114</span><br><span class="line-number">115</span><br><span class="line-number">116</span><br><span class="line-number">117</span><br><span class="line-number">118</span><br><span class="line-number">119</span><br></div></div><h3 id="_3-12-字面量类型"><a href="#_3-12-字面量类型" class="header-anchor">#</a> <strong>3.12 字面量类型</strong></h3> <p>思考以下代码，两个变量的类型分别是什么？</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">let</span> str1 <span class="token operator">=</span> <span class="token string">'Hello TS'</span>

<span class="token keyword">const</span> str2<span class="token operator">:</span> <span class="token string">'Hello TS'</span> <span class="token operator">=</span> <span class="token string">'Hello TS'</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>通过 TS 类型推论机制，可以得到答案：</p> <ol><li><p>变量 str1 的类型为：string。</p></li> <li><p>变量 str2 的类型为：'Hello TS'。</p></li></ol> <p>解释：</p> <ol><li><p>str1 是一个变量（let），它的值可以是任意字符串，所以类型为：string。</p></li> <li><p>str2 是一个常量（const），它的值不能变化只能是 'Hello TS'，所以，它的类型为：'Hello TS'。</p></li></ol> <p>注意：此处的 'Hello TS'，就是一个字面量类型。也就是说某个特定的字符串也可以作为 TS 中的类型。 除字符串外，任意的 JS 字面量（比如，对象、数字等）都可以作为类型使用。</p> <p>使用模式：<code>字面量类型配合联合类型一起使用</code>。</p> <p>使用场景：用来<code>表示一组明确的可选值列表</code>。</p> <p>比如，在贪吃蛇游戏中，游戏的方向的可选值只能是上、下、左、右中的任意一个。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">function</span> <span class="token function">changeDirection</span><span class="token punctuation">(</span>direction<span class="token operator">:</span> <span class="token string">'up'</span> <span class="token operator">|</span> <span class="token string">'down'</span> <span class="token operator">|</span> <span class="token string">'left'</span> <span class="token operator">|</span> <span class="token string">'right'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token function">changeDirection</span><span class="token punctuation">(</span><span class="token string">'left'</span><span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><p>解释：参数 direction 的值只能是 up/down/left/right 中的任意一个。</p> <p>优势：相比于 string 类型，使用字面量类型更加精确、严谨。</p> <h3 id="_3-13-枚举"><a href="#_3-13-枚举" class="header-anchor">#</a> <strong>3.13 枚举</strong></h3> <p>枚举的功能类似于字面量类型+联合类型组合的功能，也可以表示一组明确的可选值。</p> <p>枚举：定义一组命名常量。它描述一个值，该值可以是这些命名常量中的一个。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 枚举：</span>
<span class="token keyword">enum</span> Direction <span class="token punctuation">{</span>
  Up<span class="token punctuation">,</span>
  Down<span class="token punctuation">,</span>
  Left <span class="token operator">=</span> <span class="token number">5</span><span class="token punctuation">,</span>
  Right
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">changeDirection</span><span class="token punctuation">(</span>direction<span class="token operator">:</span> Direction<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token function">changeDirection</span><span class="token punctuation">(</span>Direction<span class="token punctuation">.</span>Left<span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><p><strong>解释：</strong></p> <ol><li><p>使用 enum 关键字定义枚举。</p></li> <li><p>约定枚举名称、枚举中的值以大写字母开头。</p></li> <li><p>枚举中的多个值之间通过 ,（逗号）分隔。</p></li> <li><p>定义好枚举后，直接使用枚举名称作为类型注解。</p></li></ol> <p><strong>注意</strong>：形参 direction 的类型为枚举 Direction，那么，实参的值就应该是枚举 Direction 成员的任意一个。</p> <p>访问枚举成员：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token function">changeDirection</span><span class="token punctuation">(</span>Direction<span class="token punctuation">.</span>Left<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>解释：类似于 JS 中的对象，直接通过点（.）语法访问枚举的成员。</p> <blockquote><p>问题：我们把枚举成员作为了函数的实参，它的值是什么呢？</p> <p>解释：通过将鼠标移入 Direction.Up，可以看到枚举成员 Up 的值为 0。</p> <p>注意：枚举成员是有值的，默认为：从 0 开始自增的数值。</p> <p>我们把，枚举成员的值为数字的枚举，称为：数字枚举。</p> <p>当然，也可以给枚举中的成员初始化值</p></blockquote> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 枚举：</span>

<span class="token comment">// enum Direction {</span>
<span class="token comment">//   Up,</span>
<span class="token comment">//   Down,</span>
<span class="token comment">//   Left,</span>
<span class="token comment">//   Right</span>
<span class="token comment">// }</span>

<span class="token comment">// 成员设置初始值：</span>
<span class="token comment">// enum Direction {</span>
<span class="token comment">//   Up = 10,</span>
<span class="token comment">//   Down,</span>
<span class="token comment">//   Left,</span>
<span class="token comment">//   Right</span>
<span class="token comment">// }</span>

<span class="token keyword">enum</span> Direction <span class="token punctuation">{</span>
  Up <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">,</span>
  Down <span class="token operator">=</span> <span class="token number">4</span><span class="token punctuation">,</span>
  Left <span class="token operator">=</span> <span class="token number">8</span><span class="token punctuation">,</span>
  Right <span class="token operator">=</span> <span class="token number">16</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">changeDirection</span><span class="token punctuation">(</span>direction<span class="token operator">:</span> Direction<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token function">changeDirection</span><span class="token punctuation">(</span>Direction<span class="token punctuation">.</span>Up<span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><p>字符串枚举：枚举成员的值是字符串</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 字符串枚举：</span>

<span class="token keyword">enum</span> Direction <span class="token punctuation">{</span>
  Up <span class="token operator">=</span> <span class="token string">'UP'</span><span class="token punctuation">,</span>
  Down <span class="token operator">=</span> <span class="token string">'DOWN'</span><span class="token punctuation">,</span>
  Left <span class="token operator">=</span> <span class="token string">'LEFT'</span><span class="token punctuation">,</span>
  Right <span class="token operator">=</span> <span class="token string">'RIGHT'</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token function">changeDirection</span><span class="token punctuation">(</span>direction<span class="token operator">:</span> Direction<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token function">changeDirection</span><span class="token punctuation">(</span>Direction<span class="token punctuation">.</span>Up<span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><p>注意：字符串枚举没有自增长行为，因此，字符串枚举的每个成员必须有初始值。</p> <p>枚举是 TS 为数不多的非 JavaScript 类型级扩展（不仅仅是类型）的特性之一。</p> <p>因为：其他类型仅仅被当做类型，而枚举不仅用作类型，还提供值（枚举成员都是有值的）。</p> <p>也就是说，其他的类型会在编译为 JS 代码时自动移除。但是，枚举类型会被编译为 JS 代码！</p> <p><img src="C:%5CUsers%5C85839%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20221031200039518.png" alt="image-20221031200039518"></p> <p>说明：枚举与前面讲到的字面量类型+联合类型组合的功能类似，都用来表示一组明确的可选值列表。一般情况下，推荐使用字面量类型+联合类型组合的方式，因为相比枚举，这种方式更加直观、简洁、高效。</p> <h3 id="_3-14-any-类型"><a href="#_3-14-any-类型" class="header-anchor">#</a> <strong>3.14 any 类型</strong></h3> <p>原则：<strong><code>不推荐使用 any</code></strong>！这会让 TypeScript 变为 “AnyScript”（失去 TS 类型保护的优势）。</p> <p>因为当值的类型为 any 时，可以对该值进行任意操作，并且不会有代码提示。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">let</span> obj<span class="token operator">:</span> <span class="token builtin">any</span> <span class="token operator">=</span> <span class="token punctuation">{</span> x<span class="token operator">:</span> <span class="token number">0</span> <span class="token punctuation">}</span>

<span class="token comment">// 访问不存在的属性 或者 赋值</span>
<span class="token comment">// obj.aaa</span>
<span class="token comment">// obj.aaa = 10</span>

<span class="token comment">// 当作函数调用</span>
<span class="token comment">// obj()</span>

<span class="token comment">// 赋值给其他类型的变量</span>
<span class="token comment">// let n: number = obj</span>

<span class="token comment">// --</span>

<span class="token comment">// let a</span>
<span class="token comment">// a = 1</span>
<span class="token comment">// a = ''</span>
<span class="token comment">// a()</span>

<span class="token comment">// function add(num1, num2) {}</span>
<span class="token comment">// add(1, 2)</span>
<span class="token comment">// add(1, '2')</span>
<span class="token comment">// add(1, false)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><p>解释：以上操作都不会有任何类型错误提示，即使可能存在错误！</p> <p>尽可能的避免使用 any 类型，除非临时使用 any 来“避免”书写很长、很复杂的类型！</p> <p>其他隐式具有 any 类型的情况：1 声明变量不提供类型也不提供默认值 2 函数参数不加类型。</p> <p>注意：因为不推荐使用 any，所以，这两种情况下都应该提供类型！</p> <h3 id="_3-15-typeof"><a href="#_3-15-typeof" class="header-anchor">#</a> <strong>3.15 typeof</strong></h3> <p>众所周知，JS 中提供了 typeof 操作符，用来在 JS 中获取数据的类型。</p> <div class="language-js line-numbers-mode"><pre class="language-js"><code>console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> <span class="token string">'Hello TS'</span><span class="token punctuation">)</span> <span class="token comment">// string</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>实际上，TS 也提供了 typeof 操作符：可以在<strong>类型上下文</strong>中引用变量或属性的类型（类型查询）。</p> <p>使用场景：根据已有变量的值，获取该值的类型，来简化类型书写。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">let</span> p <span class="token operator">=</span> <span class="token punctuation">{</span> x<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token number">2</span> <span class="token punctuation">}</span>

<span class="token comment">// 直接引用 p 的类型来做函数参数的类型</span>
<span class="token keyword">function</span> <span class="token function">formatPoint</span><span class="token punctuation">(</span>point<span class="token operator">:</span> <span class="token keyword">typeof</span> p<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
<span class="token comment">// function formatPoint(point: { x: number; y: number }) {}</span>
<span class="token function">formatPoint</span><span class="token punctuation">(</span><span class="token punctuation">{</span> x<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token number">100</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// --</span>

<span class="token keyword">let</span> num<span class="token operator">:</span> <span class="token keyword">typeof</span> p<span class="token punctuation">.</span>x

<span class="token keyword">function</span> <span class="token function">add</span><span class="token punctuation">(</span>num1<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> num2<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> num1 <span class="token operator">+</span> num2
<span class="token punctuation">}</span>

<span class="token comment">// 不可以使用函数调用类型</span>
<span class="token comment">// let ret: typeof add(1, 2)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br></div></div><p>解释：</p> <ol><li><p>使用 typeof 操作符来获取变量 p 的类型，结果与第一种（对象字面量形式的类型）相同。</p></li> <li><p>typeof 出现在类型注解的位置（参数名称的冒号后面）所处的环境就在类型上下文（区别于 JS 代码）。</p></li> <li><p>注意：typeof 只能用来查询变量或属性的类型，无法查询其他形式的类型（比如，函数调用的类型）</p></li></ol> <h1 id="_4-typescript-高级类型"><a href="#_4-typescript-高级类型" class="header-anchor">#</a> <strong>4. TypeScript 高级类型</strong></h1> <h2 id="概述-2"><a href="#概述-2" class="header-anchor">#</a> <strong>概述</strong></h2> <p>TS 中的高级类型有很多，重点学习以下高级类型：</p> <ol><li><p>class 类</p></li> <li><p>类型兼容性</p></li> <li><p>交叉类型</p></li> <li><p>泛型 和 keyof</p></li> <li><p>索引签名类型 和 索引查询类型</p></li> <li><p>映射类型</p></li></ol> <h2 id="_4-1-class-类"><a href="#_4-1-class-类" class="header-anchor">#</a> <strong>4.1 class 类</strong></h2> <p>TypeScript 全面支持 ES2015 中引入的 class 关键字，并为其添加了类型注解和其他语法（比如，可见性修饰符等）。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>

<span class="token keyword">const</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>根据 TS 中的类型推论，可以知道 Person 类的实例对象 p 的类型是 Person。</p></li> <li><p>TS 中的 class，不仅提供了 class 的语法功能，也作为一种类型存在。</p></li></ol></blockquote> <p><strong>实例属性初始化：</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
  age<span class="token operator">:</span> <span class="token builtin">number</span>
  gender <span class="token operator">=</span> <span class="token string">'男'</span>
  <span class="token comment">// gender: string = '男'</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

p<span class="token punctuation">.</span>age
p<span class="token punctuation">.</span>gender
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>声明成员 age，类型为 number（没有初始值）。</p></li> <li><p>声明成员 gender，并设置初始值，此时，可省略类型注解（TS 类型推论 为 string 类型）。</p></li></ol></blockquote> <p><strong>构造函数：</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
  age<span class="token operator">:</span> <span class="token builtin">number</span>
  gender<span class="token operator">:</span> <span class="token builtin">string</span>

  <span class="token function">constructor</span><span class="token punctuation">(</span>age<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> gender<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age
    <span class="token keyword">this</span><span class="token punctuation">.</span>gender <span class="token operator">=</span> gender
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Person</span><span class="token punctuation">(</span><span class="token number">18</span><span class="token punctuation">,</span> <span class="token string">'男'</span><span class="token punctuation">)</span>
<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span>age<span class="token punctuation">,</span> p<span class="token punctuation">.</span>gender<span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>成员初始化（比如，age: number）后，才可以通过 this.age 来访问实例成员。</p></li> <li><p>需要为构造函数指定类型注解，否则会被隐式推断为 any；构造函数不需要返回值类型。</p></li></ol></blockquote> <p><strong>实例方法:</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">class</span> <span class="token class-name">Point</span> <span class="token punctuation">{</span>
  x <span class="token operator">=</span> <span class="token number">1</span>
  y <span class="token operator">=</span> <span class="token number">2</span>

  <span class="token function">scale</span><span class="token punctuation">(</span>n<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>x <span class="token operator">*=</span> n
    <span class="token keyword">this</span><span class="token punctuation">.</span>y <span class="token operator">*=</span> n
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> p <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Point</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

p<span class="token punctuation">.</span><span class="token function">scale</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span>

<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>p<span class="token punctuation">.</span>x<span class="token punctuation">,</span> p<span class="token punctuation">.</span>y<span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><blockquote><p>解释：方法的类型注解（参数和返回值）与函数用法相同。</p></blockquote> <p>类继承的两种方式：1 .extends（继承父类）  2 .implements（实现接口）。</p> <p>说明：JS 中只有 extends，而 implements 是 TS 提供的。</p> <p><strong>extends（继承父类）：</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">class</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'走两步'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Dog</span> <span class="token keyword">extends</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  name <span class="token operator">=</span> <span class="token string">'二哈'</span>

  <span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'旺旺！'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> d <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Dog</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
d<span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
d<span class="token punctuation">.</span><span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>d<span class="token punctuation">.</span>name<span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>通过 extends 关键字实现继承。</p></li> <li><p>子类 Dog 继承父类 Animal，则 Dog 的实例对象 dog 就同时具有了父类 Animal 和 子类 Dog 的所有属性和方法。</p></li></ol></blockquote> <p>类继承的两种方式：1 extends（继承父类） 2 implements（实现接口）</p> <p><strong>implements（实现接口）</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">Singale</span> <span class="token punctuation">{</span>
  <span class="token function">sing</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token keyword">implements</span> <span class="token class-name">Singale</span> <span class="token punctuation">{</span>
  name <span class="token operator">=</span> <span class="token string">'jack'</span>

  <span class="token function">sing</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'你是我的小呀小苹果'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>通过 implements 关键字让 class 实现接口。</p></li> <li><p>Person 类实现接口 Singable 意味着，Person 类中必须提供 Singable 接口中指定的所有方法和属性。</p></li></ol></blockquote> <p>类成员可见性：可以使用 TS 来控制 class 的方法或属性对于 class 外的代码是否可见。</p> <p><code>可见性修饰符包括：1 public（公有的） 2 protected（受保护的） 3 private（私有的）</code>。</p> <p><strong>1.<code>public</code>：表示公有的、公开的，公有成员可以被任何地方访问，默认可见性。默认可以不写就是public。</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 父类</span>
<span class="token keyword">class</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token keyword">public</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'走两步'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> a <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Animal</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
a<span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 子类</span>
<span class="token keyword">class</span> <span class="token class-name">Dog</span> <span class="token keyword">extends</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'旺旺！'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> d <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Dog</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
d<span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>在类属性或方法前面添加 public 关键字，来修饰该属性或方法是共有的。</p></li> <li><p>因为 public 是默认可见性，所以，<code>可以直接省略</code>。</p></li></ol></blockquote> <p><strong>2. protected：表示受保护的，仅对其声明所在类和子类中（非实例对象）可见。</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 父类</span>
<span class="token keyword">class</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token comment">// 这个方法是受保护的</span>
  <span class="token keyword">protected</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'走两步'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'跑起来'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> a <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Animal</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// a.move()  访问不到</span>

<span class="token comment">// 子类 子类可以访问私有的</span>
<span class="token keyword">class</span> <span class="token class-name">Dog</span> <span class="token keyword">extends</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'旺旺！'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> d <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Dog</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// d</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>在类属性或方法前面添加 protected 关键字，来修饰该属性或方法是受保护的。</p></li> <li><p>在子类的方法内部可以通过 this 来访问父类中受保护的成员，但是，对实例不可见！</p></li></ol></blockquote> <p><strong>3. private：表示私有的，只在当前类中可见，对实例对象以及子类也是不可见的。</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 父类</span>
<span class="token keyword">class</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token keyword">private</span> <span class="token function">__run__</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Animal 内部辅助函数'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 受保护的</span>
  <span class="token keyword">protected</span> <span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">__run__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'走两步'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>

  <span class="token comment">// 公开的</span>
  <span class="token function">run</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">__run__</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">move</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'跑起来'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> a <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Animal</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// a.</span>

<span class="token comment">// 子类</span>
<span class="token keyword">class</span> <span class="token class-name">Dog</span> <span class="token keyword">extends</span> <span class="token class-name">Animal</span> <span class="token punctuation">{</span>
  <span class="token function">bark</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token comment">// this.</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'旺旺！'</span><span class="token punctuation">)</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> d <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Dog</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// d.</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>在类属性或方法前面添加 private 关键字，来修饰该属性或方法是私有的。</p></li> <li><p>私有的属性或方法只在当前类中可见，对子类和实例对象也都是不可见的！</p></li></ol></blockquote> <p><strong>除了可见性修饰符之外，还有一个常见修饰符就是：readonly（只读修饰符）。<code>readonly：表示只读，用来防止在构造函数之外对属性进行赋值</code>。</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">/* class Person {
  // 只读属性
  readonly age: number = 18

  constructor(age: number) {
    this.age = age
  }

  // 错误演示：
  // readonly setAge() {
  //   // this.age = 20
  // }
} */</span>

<span class="token keyword">class</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
  <span class="token comment">// 只读属性</span>
  <span class="token comment">// 注意：只要是 readonly 来修饰的属性，必须手动提供明确的类型</span>
  <span class="token keyword">readonly</span> age<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=</span> <span class="token number">18</span>

  <span class="token function">constructor</span><span class="token punctuation">(</span>age<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token comment">// --</span>

<span class="token comment">// interface IPerson {</span>
<span class="token comment">//   readonly name: string</span>
<span class="token comment">// }</span>

<span class="token comment">// let obj: IPerson = {</span>
<span class="token comment">//   name: 'jack'</span>
<span class="token comment">// }</span>

<span class="token keyword">let</span> obj<span class="token operator">:</span> <span class="token punctuation">{</span> <span class="token keyword">readonly</span> name<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'jack'</span>
<span class="token punctuation">}</span>

<span class="token comment">// 这里 name 显示无法赋值，</span>
obj<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">'rose'</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br><span class="line-number">37</span><br><span class="line-number">38</span><br><span class="line-number">39</span><br><span class="line-number">40</span><br><span class="line-number">41</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>使用 readonly 关键字修饰该属性是只读的，注意只能修饰属性不能修饰方法。</p></li> <li><p>注意：属性 age 后面的类型注解（比如，此处的 number）如果不加，则 age 的类型为 18 （字面量类型）。</p></li> <li><p>接口或者 {} 表示的对象类型，也可以使用 readonly。</p></li></ol></blockquote> <h2 id="_4-2-类型兼容性"><a href="#_4-2-类型兼容性" class="header-anchor">#</a> <strong>4.2 类型兼容性</strong></h2> <p>两种类型系统：1 Structural Type System（结构化类型系统） 2 Nominal Type System（标明类型系统）。</p> <p>TS 采用的是结构化类型系统，也叫做 duck typing（鸭子类型），类型检查关注的是值所具有的形状。</p> <p>也就是说，在结构类型系统中，如果两个对象具有相同的形状，则认为它们属于同一类型。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 演示类型兼容性：</span>

<span class="token comment">// let arr = ['a', 'b', 'c']</span>

<span class="token comment">// arr.forEach(item =&gt; {})</span>
<span class="token comment">// arr.forEach((item, index) =&gt; {})</span>
<span class="token comment">// arr.forEach((item, index, array) =&gt; {})</span>

<span class="token comment">// 两个类的兼容性演示：</span>
<span class="token keyword">class</span> <span class="token class-name">Point</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>
<span class="token keyword">class</span> <span class="token class-name">Point2D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> p<span class="token operator">:</span> Point <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Point2D</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>Point 和 Point2D 是两个名称不同的类。</p></li> <li><p>变量 p 的类型被显示标注为 Point 类型，但是，它的值却是 Point2D 的实例，并且没有类型错误。</p></li> <li><p>因为 TS 是结构化类型系统，只检查 Point 和 Point2D 的结构是否相同（相同，都具有 x 和 y 两个属性，属性类型也相同）。</p></li> <li><p>但是，如果在 Nominal Type System 中（比如，C#、Java 等），它们是不同的类，类型无法兼容。</p></li></ol></blockquote> <p><strong>注意：在结构化类型系统中，如果两个对象具有相同的形状，则认为它们属于同一类型，这种说法并不准确。</strong> 更准确的说法：对于对象类型来说，y 的成员至少与 x 相同，则 x 兼容 y（<strong>成员多的可以赋值给少的</strong>）。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 两个类的兼容性演示：</span>

<span class="token keyword">class</span> <span class="token class-name">Point</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>
<span class="token keyword">class</span> <span class="token class-name">Point2D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> p<span class="token operator">:</span> Point <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Point2D</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token keyword">class</span> <span class="token class-name">Point3D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
  z<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>

<span class="token keyword">const</span> p1<span class="token operator">:</span> Point <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Point3D</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 错误演示</span>
<span class="token comment">// const p2: Point3D = new Point()</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>Point3D 的成员至少与 Point 相同，则 Point 兼容 Point3D。</p></li> <li><p>所以，<code>成员多的 Point3D 可以赋值给成员少的 Point</code>。</p></li></ol></blockquote> <p><strong>除了 class 之外，TS 中的其他类型也存在相互兼容的情况，包括：1 接口兼容性 2 函数兼容性等。</strong></p> <ul><li>接口之间的兼容性，类似于 class。并且，class 和 interface 之间也可以兼容。</li></ul> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">Point</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>
<span class="token keyword">interface</span> <span class="token class-name">Point2D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>
<span class="token keyword">interface</span> <span class="token class-name">Point3D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
  z<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> p1<span class="token operator">:</span> Point
<span class="token keyword">let</span> p2<span class="token operator">:</span> Point2D
<span class="token keyword">let</span> p3<span class="token operator">:</span> Point3D

<span class="token comment">// 正确：</span>
<span class="token comment">// p1 = p2</span>
<span class="token comment">// p2 = p1</span>
<span class="token comment">// p1 = p3</span>

<span class="token comment">// 错误演示：</span>
<span class="token comment">// p3 = p1</span>

<span class="token comment">// 类和接口之间也是兼容的</span>
<span class="token keyword">class</span> <span class="token class-name">Point4D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
  z<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>
p2 <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Point4D</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br></div></div><ul><li>函数之间兼容性比较复杂，需要考虑：1 参数个数 2 参数类型 3 返回值类型。</li></ul> <ol><li>参数个数，参数多的兼容参数少的（或者说，<strong>参数少的可以赋值给多的</strong>）。</li></ol> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 1 参数个数： 参数少的可以赋值给参数多的</span>
<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">F1</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span>a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">void</span>
<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">F2</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span>a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> b<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">void</span>

<span class="token keyword">let</span> f1<span class="token operator">:</span> <span class="token constant">F1</span>
<span class="token keyword">let</span> f2<span class="token operator">:</span> <span class="token constant">F2</span>

f2 <span class="token operator">=</span> f1

<span class="token comment">// 错误演示：</span>
<span class="token comment">// f1 = f2</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>参数少的可以赋值给参数多的，所以，f1 可以赋值给 f2。</p></li> <li><p>数组 forEach 方法的第一个参数是回调函数，该示例中类型为：(value: string, index: number, array: string[]) =&gt; void。</p></li> <li><p><code>在 JS 中省略用不到的函数参数实际上是很常见的，这样的使用方式，促成了 TS 中函数类型之间的兼容性</code>。</p></li> <li><p>并且因为回调函数是有类型的，所以，TS 会自动推导出参数 item、index、array 的类型。</p></li></ol></blockquote> <ul><li>函数之间兼容性比较复杂，需要考虑：1 参数个数 2 参数类型 3 返回值类型。</li></ul> <ol start="2"><li>参数类型，相同位置的参数类型要相同（原始类型）或兼容（对象类型）</li></ol> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 2 参数类型： 相同位置的参数类型要相同或兼容</span>

<span class="token comment">// 原始类型：</span>
<span class="token comment">// type F1 = (a: number) =&gt; void</span>
<span class="token comment">// type F2 = (a: number) =&gt; void</span>

<span class="token comment">// let f1: F1</span>
<span class="token comment">// let f2: F2</span>

<span class="token comment">// f1 = f2</span>
<span class="token comment">// f2 = f1</span>

<span class="token comment">// --</span>

<span class="token comment">// 对象类型</span>
<span class="token keyword">interface</span> <span class="token class-name">Point2D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>
<span class="token keyword">interface</span> <span class="token class-name">Point3D</span> <span class="token punctuation">{</span>
  x<span class="token operator">:</span> <span class="token builtin">number</span>
  y<span class="token operator">:</span> <span class="token builtin">number</span>
  z<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">F2</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span>p<span class="token operator">:</span> Point2D<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">void</span> <span class="token comment">// 相当于有 2 个参数</span>
<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">F3</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span>p<span class="token operator">:</span> Point3D<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token keyword">void</span> <span class="token comment">// 相当于有 3 个参数</span>

<span class="token keyword">let</span> f2<span class="token operator">:</span> <span class="token constant">F2</span>
<span class="token keyword">let</span> f3<span class="token operator">:</span> <span class="token constant">F3</span>

f3 <span class="token operator">=</span> f2

<span class="token comment">// f2 = f3</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br></div></div><blockquote><p>解释：函数类型 F2 兼容函数类型 F1，因为 F1 和 F2 的第一个参数类型相同。</p></blockquote> <ul><li>函数之间兼容性比较复杂，需要考虑：1 参数个数 2 参数类型 3 返回值类型。</li></ul> <ol start="2"><li>参数类型，相同位置的参数类型要相同或兼容。</li></ol> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 3 返回值类型，只需要关注返回值类型本身即可</span>

<span class="token comment">// 原始类型：</span>
<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">F5</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token builtin">string</span>
<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">F6</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token builtin">string</span>

<span class="token keyword">let</span> f5<span class="token operator">:</span> <span class="token constant">F5</span>
<span class="token keyword">let</span> f6<span class="token operator">:</span> <span class="token constant">F6</span>

f6 <span class="token operator">=</span> f5
f5 <span class="token operator">=</span> f6

<span class="token comment">// 对象类型：</span>
<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">F7</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span>
<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">F8</span></span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> age<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">}</span>

<span class="token keyword">let</span> f7<span class="token operator">:</span> <span class="token constant">F7</span>
<span class="token keyword">let</span> f8<span class="token operator">:</span> <span class="token constant">F8</span>

f7 <span class="token operator">=</span> f8

<span class="token comment">// 错误演示</span>
<span class="token comment">// f8 = f7</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>如果返回值类型是原始类型，此时两个类型要相同，比如，左侧类型 F5 和 F6。</p></li> <li><p>如果返回值类型是对象类型，此时成员多的可以赋值给成员少的，比如，右侧类型 F7 和 F8。</p></li></ol></blockquote> <h2 id="_4-3-交叉类型"><a href="#_4-3-交叉类型" class="header-anchor">#</a> <strong>4.3 交叉类型</strong></h2> <p>交叉类型（&amp;）：功能类似于接口继承（extends），用于组合多个类型为一个类型（<strong>常用于对象类型</strong>）。比如，</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// interface Point2D {</span>
<span class="token comment">//   x: number</span>
<span class="token comment">//   y: number</span>
<span class="token comment">// }</span>

<span class="token comment">// // 通过继承 Point3D 具有 x/y/z 三个属性</span>
<span class="token comment">// interface Point3D extends Point2D {</span>
<span class="token comment">//   z: number</span>
<span class="token comment">// }</span>

<span class="token comment">// let p3: Point3D = {</span>
<span class="token comment">//   x: 1,</span>
<span class="token comment">//   y: 2,</span>
<span class="token comment">//   z: 3</span>
<span class="token comment">// }</span>

<span class="token comment">// --</span>

<span class="token keyword">interface</span> <span class="token class-name">Person</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span>
  <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>
<span class="token keyword">interface</span> <span class="token class-name">Contact</span> <span class="token punctuation">{</span>
  phone<span class="token operator">:</span> <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">PersonDetail</span> <span class="token operator">=</span> Person <span class="token operator">&amp;</span> Contact

<span class="token keyword">let</span> obj<span class="token operator">:</span> PersonDetail <span class="token operator">=</span> <span class="token punctuation">{</span>
  name<span class="token operator">:</span> <span class="token string">'jack'</span><span class="token punctuation">,</span>
  phone<span class="token operator">:</span> <span class="token string">'133....'</span><span class="token punctuation">,</span>
  <span class="token function">say</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token number">1</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br><span class="line-number">35</span><br><span class="line-number">36</span><br></div></div><blockquote><p>解释：使用交叉类型后，新的类型 PersonDetail 就同时具备了 Person 和 Contact 的所有属性类型。相当于，</p></blockquote> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">type</span> <span class="token class-name">PersonDetail</span> <span class="token operator">=</span> <span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> phone<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><strong>交叉类型（&amp;）和接口继承（extends）的对比：</strong></p> <ul><li><p>相同点：都可以实现对象类型的组合。</p></li> <li><p>不同点：两种方式实现类型组合时，对于同名属性之间，处理类型冲突的方式不同。</p></li></ul> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 对比：</span>
<span class="token comment">// 继承</span>
<span class="token comment">// interface A {</span>
<span class="token comment">//   fn: (value: number) =&gt; string</span>
<span class="token comment">// }</span>
<span class="token comment">// 这里 B 会报错</span>
<span class="token comment">// interface B extends A {</span>
<span class="token comment">//   fn: (value: string) =&gt; string</span>
<span class="token comment">// }</span>

<span class="token comment">// -- 交叉类型</span>
<span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">A</span></span> <span class="token punctuation">{</span>
  <span class="token function-variable function">fn</span><span class="token operator">:</span> <span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">|</span> <span class="token builtin">boolean</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token builtin">string</span>
<span class="token punctuation">}</span>
<span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">B</span></span> <span class="token punctuation">{</span>
  <span class="token function-variable function">fn</span><span class="token operator">:</span> <span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token builtin">string</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name"><span class="token constant">C</span></span> <span class="token operator">=</span> <span class="token constant">A</span> <span class="token operator">&amp;</span> <span class="token constant">B</span>

<span class="token keyword">let</span> c<span class="token operator">:</span> <span class="token constant">C</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token function">fn</span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">|</span> <span class="token builtin">string</span> <span class="token operator">|</span> <span class="token builtin">boolean</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> value <span class="token operator">+</span> <span class="token string">''</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>c<span class="token punctuation">.</span><span class="token function">fn</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>


<span class="token comment">// let c: C = {</span>
<span class="token comment">//   fn(value: string) {}</span>
<span class="token comment">// }</span>

<span class="token comment">// let c: C = A.fn(11) =&gt; { console.log(11) }</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br><span class="line-number">24</span><br><span class="line-number">25</span><br><span class="line-number">26</span><br><span class="line-number">27</span><br><span class="line-number">28</span><br><span class="line-number">29</span><br><span class="line-number">30</span><br><span class="line-number">31</span><br><span class="line-number">32</span><br><span class="line-number">33</span><br><span class="line-number">34</span><br></div></div><p>说明：以上代码，接口继承会报错（类型不兼容）；<code>交叉类型没有错误，可以简单的理解为</code>：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token function-variable function">fn</span><span class="token operator">:</span> <span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">|</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> <span class="token builtin">string</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><h2 id="_4-4-泛型"><a href="#_4-4-泛型" class="header-anchor">#</a> <strong>4.4 泛型</strong></h2> <p>泛型是可以在保证类型安全前提下，让函数等与多种类型一起工作，从而实现复用，常用于：函数、接口、class 中。</p> <p>需求：创建一个 id 函数，传入什么数据就返回该数据本身（也就是说，参数和返回值类型相同）。</p> <div class="language-js line-numbers-mode"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">id</span><span class="token punctuation">(</span><span class="token parameter"><span class="token literal-property property">value</span><span class="token operator">:</span> number</span><span class="token punctuation">)</span><span class="token operator">:</span> number <span class="token punctuation">{</span> <span class="token keyword">return</span> value <span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p>比如，id(10) 调用以上函数就会直接返回 10 本身。但是，该函数只接收数值类型，无法用于其他类型。</p> <p>为了能让函数能够接受任意类型，可以将参数类型修改为 any。但是，这样就失去了 TS 的类型保护，类型不安全。</p> <div class="language-js line-numbers-mode"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">id</span><span class="token punctuation">(</span><span class="token parameter"><span class="token literal-property property">value</span><span class="token operator">:</span> any</span><span class="token punctuation">)</span><span class="token operator">:</span> any <span class="token punctuation">{</span> <span class="token keyword">return</span> value <span class="token punctuation">}</span>   <span class="token comment">// 不安全</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><p><strong>泛型</strong>在<strong>保证类型安全</strong>（不丢失类型信息）的同时，可以<strong>让函数等与多种不同的类型一起工作</strong>，灵活可<strong>复用</strong>。</p> <p>实际上，在 C＃和 Java 等编程语言中，泛型都是用来实现可复用组件功能的主要工具之一。</p> <p><strong>创建泛型函数：</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>value<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token constant">T</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> value <span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>语法：在函数名称的后面添加 &lt;&gt;（尖括号），尖括号中添加类型变量，比如此处的 Type。</p></li> <li><p>类型变量 Type，是一种特殊类型的变量，它处理类型而不是值。</p></li> <li><p>该类型变量相当于一个类型容器，能够捕获用户提供的类型（具体是什么类型由用户调用该函数时指定）。</p></li> <li><p>因为 Type 是类型，因此可以将其作为函数参数和返回值的类型，表示参数和返回值具有相同的类型。</p></li> <li><p>类型变量 Type，可以是任意合法的变量名称。</p></li></ol></blockquote> <p><strong>调用泛型函数：</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 使用泛型来创建一个函数：</span>

<span class="token keyword">function</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span>Type<span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>value<span class="token operator">:</span> Type<span class="token punctuation">)</span><span class="token operator">:</span> Type <span class="token punctuation">{</span>
  <span class="token keyword">return</span> value
<span class="token punctuation">}</span>

<span class="token comment">// 调用泛型函数：</span>

<span class="token comment">// 1 以 number 类型调用泛型函数</span>
<span class="token keyword">const</span> num <span class="token operator">=</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span>

<span class="token comment">// 2 以 string 类型调用泛型函数</span>
<span class="token keyword">const</span> str <span class="token operator">=</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token builtin">string</span><span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> ret <span class="token operator">=</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token builtin">boolean</span><span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>语法：在函数名称的后面添加 &lt;&gt;（尖括号），尖括号中指定具体的类型，比如，此处的 number。</p></li> <li><p>当传入类型 number 后，这个类型就会被函数声明时指定的类型变量 Type 捕获到。</p></li> <li><p>此时，Type 的类型就是 number，所以，函数 id 参数和返回值的类型也都是 number。</p></li></ol> <p>同样，如果传入类型 string，函数 id 参数和返回值的类型就都是 string。</p> <p>这样，通过泛型就做到了让 id 函数与多种不同的类型一起工作，实现了复用的同时保证了类型安全。</p></blockquote> <p><strong>简化调用泛型函数：</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// 使用泛型来创建一个函数：</span>
<span class="token keyword">function</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span>Type<span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>value<span class="token operator">:</span> Type<span class="token punctuation">)</span><span class="token operator">:</span> Type <span class="token punctuation">{</span>
  <span class="token keyword">return</span> value
<span class="token punctuation">}</span>

<span class="token comment">// 调用泛型函数：</span>

<span class="token comment">// 1 以 number 类型调用泛型函数</span>
<span class="token keyword">const</span> num <span class="token operator">=</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">)</span>

<span class="token comment">// 2 以 string 类型调用泛型函数</span>
<span class="token keyword">const</span> str <span class="token operator">=</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token builtin">string</span><span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span><span class="token string">'a'</span><span class="token punctuation">)</span>

<span class="token comment">// --</span>

<span class="token keyword">let</span> num1 <span class="token operator">=</span> <span class="token function">id</span><span class="token punctuation">(</span><span class="token number">100</span><span class="token punctuation">)</span>
<span class="token keyword">let</span> str1 <span class="token operator">=</span> <span class="token function">id</span><span class="token punctuation">(</span><span class="token string">'abc'</span><span class="token punctuation">)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>在调用泛型函数时，可以省略 &lt;类型&gt; 来简化泛型函数的调用。</p></li> <li><p>此时，TS 内部会采用一种叫做类型参数推断的机制，来根据传入的实参自动推断出类型变量 Type 的类型。</p></li> <li><p>比如，传入实参 10，TS 会自动推断出变量 num 的类型 number，并作为 Type 的类型。</p></li></ol> <p>推荐：使用这种简化的方式调用泛型函数，使代码更短，更易于阅读。</p> <p>说明：当编译器无法推断类型或者推断的类型不准确时，就需要显式地传入类型参数。</p></blockquote> <p><strong>泛型约束:</strong></p> <p>泛型约束：默认情况下，泛型函数的类型变量 Type 可以代表多个类型，这导致无法访问任何属性。比如，id('a') 调用函数时获取参数的长度：</p> <p><img src="https://img-blog.csdnimg.cn/12f20bb509d14fc8b5950c350301e0cb.png" alt="在这里插入图片描述"></p> <blockquote><p>解释：Type 可以代表任意类型，无法保证一定存在 length 属性，比如 number 类型就没有 length。</p> <p>此时，就需要为泛型添加约束来<strong>收缩类型</strong>（缩窄类型取值范围）。</p></blockquote> <p><strong>添加泛型约束收缩类型</strong>，主要有以下两种方式：1 <code>指定更加具体的类型</code> 2 <code>添加约束</code>。</p> <ol><li>指定更加具体的类型</li></ol> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span>Type<span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>value<span class="token operator">:</span> Type<span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token operator">:</span> Type<span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token punctuation">{</span>
  value<span class="token punctuation">.</span>length
  <span class="token keyword">return</span> value
<span class="token punctuation">}</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><p>比如，将类型修改为 Type[]（Type 类型的数组），因为只要是数组就一定存在 length 属性，因此就可以访问了。</p> <ol start="2"><li>添加约束</li></ol> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">ILength</span> <span class="token punctuation">{</span>
  length<span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>

<span class="token keyword">function</span> <span class="token generic-function"><span class="token function">id</span><span class="token generic class-name"><span class="token operator">&lt;</span>Type <span class="token keyword">extends</span> ILength<span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>value<span class="token operator">:</span> Type<span class="token punctuation">)</span><span class="token operator">:</span> Type <span class="token punctuation">{</span>
  value<span class="token punctuation">.</span>length
  <span class="token keyword">return</span> value
<span class="token punctuation">}</span>

<span class="token function">id</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">,</span> <span class="token string">'c'</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token function">id</span><span class="token punctuation">(</span><span class="token string">'abc'</span><span class="token punctuation">)</span>
<span class="token function">id</span><span class="token punctuation">(</span><span class="token punctuation">{</span> length<span class="token operator">:</span> <span class="token number">10</span><span class="token punctuation">,</span> name<span class="token operator">:</span> <span class="token string">'jack'</span> <span class="token punctuation">}</span><span class="token punctuation">)</span>

<span class="token comment">// 错误演示</span>
<span class="token comment">// id(123)</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>创建描述约束的接口 ILength，该接口要求提供 length 属性。</p></li> <li><p>通过 extends 关键字使用该接口，为泛型（类型变量）添加约束。</p></li> <li><p>该约束表示：传入的类型必须具有 length 属性。</p></li></ol> <p>注意：传入的实参（比如，数组）只要有 length 属性即可，这也符合前面讲到的接口的类型兼容性。</p></blockquote> <p>泛型的类型变量可以有多个，并且<code>类型变量之间还可以约束</code>（比如，第二个类型变量受第一个类型变量约束）。</p> <p>比如，创建一个函数来获取对象中属性的值：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">getProp</span><span class="token generic class-name"><span class="token operator">&lt;</span>Type<span class="token punctuation">,</span> Key <span class="token keyword">extends</span> <span class="token keyword">keyof</span> Type<span class="token operator">&gt;</span></span></span><span class="token punctuation">(</span>obj<span class="token operator">:</span> Type<span class="token punctuation">,</span> key<span class="token operator">:</span> Key<span class="token punctuation">)</span> <span class="token punctuation">{</span>
  <span class="token keyword">return</span> obj<span class="token punctuation">[</span>key<span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token function">getProp</span><span class="token punctuation">(</span><span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'jack'</span><span class="token punctuation">,</span> age<span class="token operator">:</span> <span class="token number">18</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">'age'</span><span class="token punctuation">)</span>
<span class="token function">getProp</span><span class="token punctuation">(</span><span class="token punctuation">{</span> name<span class="token operator">:</span> <span class="token string">'jack'</span><span class="token punctuation">,</span> age<span class="token operator">:</span> <span class="token number">18</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token string">'name'</span><span class="token punctuation">)</span>

<span class="token comment">// 补充：（了解）</span>
<span class="token function">getProp</span><span class="token punctuation">(</span><span class="token number">18</span><span class="token punctuation">,</span> <span class="token string">'toFixed'</span><span class="token punctuation">)</span>
<span class="token function">getProp</span><span class="token punctuation">(</span><span class="token string">'abc'</span><span class="token punctuation">,</span> <span class="token string">'split'</span><span class="token punctuation">)</span>
<span class="token function">getProp</span><span class="token punctuation">(</span><span class="token string">'abc'</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token comment">// 此处 1 表示索引</span>
<span class="token function">getProp</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string">'length'</span><span class="token punctuation">)</span>
<span class="token function">getProp</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span>

<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'object'</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token comment">// b</span>

<span class="token comment">// 错误演示：</span>
<span class="token comment">// getProp({ name: 'jack', age: 18 }, 'name1')</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>添加了第二个类型变量 Key，两个类型变量之间使用（,）逗号分隔。</p></li> <li><p>keyof 关键字接收一个对象类型，生成其键名称（可能是字符串或数字）的联合类型。</p></li> <li><p>本示例中 keyof Type 实际上获取的是 person 对象所有键的联合类型，也就是：'name' | 'age'。</p></li> <li><p>类型变量 Key 受 Type 约束，可以理解为：Key 只能是 Type 所有键中的任意一个，或者说只能访问对象中存在的属性。</p></li></ol></blockquote> <p><strong>泛型接口:</strong></p> <p>泛型接口：接口也可以配合泛型来使用，以增加其灵活性，增强其复用性。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">IdFunc<span class="token operator">&lt;</span>Type<span class="token operator">&gt;</span></span> <span class="token punctuation">{</span>
  <span class="token function-variable function">id</span><span class="token operator">:</span> <span class="token punctuation">(</span>value<span class="token operator">:</span> Type<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> Type
  <span class="token function-variable function">ids</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=&gt;</span> Type<span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> obj<span class="token operator">:</span> IdFunc<span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">&gt;</span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token function">id</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> value
  <span class="token punctuation">}</span><span class="token punctuation">,</span>
  <span class="token function">ids</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    <span class="token keyword">return</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span>
  <span class="token punctuation">}</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>在接口名称的后面添加 &lt;类型变量&gt;，那么，这个接口就变成了泛型接口。</p></li> <li><p>接口的类型变量，对接口中所有其他成员可见，也就是接口中所有成员都可以使用类型变量。</p></li> <li><p>使用泛型接口时，需要显式指定具体的类型（比如，此处的<code>IdFunc&lt;nunber&gt;</code>）。</p></li> <li><p>此时，id 方法的参数和返回值类型都是 number；ids 方法的返回值类型是 number[]。</p></li></ol></blockquote> <p>实际上，JS 中的数组在 TS 中就是一个泛型接口。</p> <p><img src="https://img-blog.csdnimg.cn/89a36a20179e48cc804890a802364acd.png" alt="在这里插入图片描述"></p> <blockquote><p>解释：当我们在使用数组时，TS 会根据数组的不同类型，来自动将类型变量设置为相应的类型。</p> <p>技巧：可以通过 Ctrl + 鼠标左键（Mac：option + 鼠标左键）来查看具体的类型信息。</p></blockquote> <p><strong>泛型类：class 也可以配合泛型来使用。</strong></p> <p>比如，React 的 class 组件的基类 Component 就是泛型类，不同的组件有不同的 props 和 state。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token comment">// class GenericNumber&lt;NumType&gt; {</span>
<span class="token comment">//   defaultValue: NumType</span>
<span class="token comment">//   add: (x: NumType, y: NumType) =&gt; NumType</span>

<span class="token comment">//   constructor(value: NumType) {</span>
<span class="token comment">//     this.defaultValue = value</span>
<span class="token comment">//   }</span>
<span class="token comment">// }</span>
<span class="token comment">// 此时，可以省略 &lt;类型&gt; 不写。因为 TS 可以根据传入的参数自动推导出类型</span>
<span class="token comment">// const myNum = new GenericNumber(100)</span>
<span class="token comment">// myNum.defaultValue = 10</span>

<span class="token comment">// --</span>

<span class="token keyword">class</span> <span class="token class-name">GenericNumber<span class="token operator">&lt;</span>NumType<span class="token operator">&gt;</span></span> <span class="token punctuation">{</span>
  defaultValue<span class="token operator">:</span> NumType
  <span class="token function-variable function">add</span><span class="token operator">:</span> <span class="token punctuation">(</span>x<span class="token operator">:</span> NumType<span class="token punctuation">,</span> y<span class="token operator">:</span> NumType<span class="token punctuation">)</span> <span class="token operator">=&gt;</span> NumType
<span class="token punctuation">}</span>

<span class="token comment">// 这种情况下，推荐明确指定 &lt;类型&gt;。因为 TS 无法推导出类型</span>
<span class="token keyword">const</span> myNum <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">GenericNumber</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
myNum<span class="token punctuation">.</span>defaultValue <span class="token operator">=</span> <span class="token number">10</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br><span class="line-number">17</span><br><span class="line-number">18</span><br><span class="line-number">19</span><br><span class="line-number">20</span><br><span class="line-number">21</span><br><span class="line-number">22</span><br><span class="line-number">23</span><br></div></div><blockquote><p>解释：React.Component 泛型类两个类型变量，分别指定 props 和 state 类型。</p> <ol><li><p>类似于泛型接口，在 class 名称后面添加 &lt;类型变量&gt;，这个类就变成了泛型类。</p></li> <li><p>此处的 add 方法，采用的是箭头函数形式的类型书写方式。</p></li></ol></blockquote> <p>类似于泛型接口，在创建 class 实例时，在类名后面通过 &lt;类型&gt; 来指定明确的类型。</p> <p><strong>泛型工具类型：TS 内置了一些常用的工具类型，来简化 TS 中的一些常见操作。</strong></p> <p>说明：它们都是基于泛型实现的（泛型适用于多种类型，更加通用），并且是内置的，可以直接在代码中使用。</p> <p>这些工具类型有很多，主要学习以下几个：</p> <ol><li><p><code>Partial&lt;Type&gt;</code></p></li> <li><p><code>Readonly&lt;Type&gt;</code></p></li> <li><p><code>Pick&lt;Type, Keys&gt;</code></p></li> <li><p><code>Record&lt;Keys, Type&gt;</code></p></li></ol> <p>泛型工具类型 - <code>Partial&lt;Type&gt;</code> 用来构造（创建）一个类型，将 Type 的所有属性设置为可选。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">Props</span> <span class="token punctuation">{</span>
  id<span class="token operator">:</span> <span class="token builtin">string</span>
  children<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">PartialProps</span> <span class="token operator">=</span> Partial<span class="token operator">&lt;</span>Props<span class="token operator">&gt;</span>

<span class="token keyword">let</span> p1<span class="token operator">:</span> Props <span class="token operator">=</span> <span class="token punctuation">{</span>
  id<span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span>
  children<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>
<span class="token keyword">let</span> p2<span class="token operator">:</span> PartialProps <span class="token operator">=</span> <span class="token punctuation">{</span>
  id<span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span>
  children<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br><span class="line-number">16</span><br></div></div><blockquote><p>解释：构造出来的新类型 PartialProps 结构和 Props 相同，但所有属性都变为可选的。</p></blockquote> <p>泛型工具类型 - <code>Readonly&lt;Type&gt;</code> 用来构造一个类型，将 Type 的所有属性都设置为 readonly（只读）。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">Props</span> <span class="token punctuation">{</span>
  id<span class="token operator">:</span> <span class="token builtin">string</span>
  children<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">ReadonlyProps</span> <span class="token operator">=</span> Readonly<span class="token operator">&lt;</span>Props<span class="token operator">&gt;</span>

<span class="token keyword">let</span> p1<span class="token operator">:</span> ReadonlyProps <span class="token operator">=</span> <span class="token punctuation">{</span>
  id<span class="token operator">:</span> <span class="token string">'1'</span><span class="token punctuation">,</span>
  children<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token comment">// 这里赋值就报错 只读</span>
p1<span class="token punctuation">.</span>id <span class="token operator">=</span> <span class="token string">'2'</span>
<span class="token comment">// 当我们想重新给 id 属性赋值时，就会报错：无法分配到 &quot;id&quot; ，因为它是只读属性。</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br><span class="line-number">15</span><br></div></div><blockquote><p>解释：构造出来的新类型 ReadonlyProps 结构和 Props 相同，但所有属性都变为只读的。</p></blockquote> <p>泛型工具类型 - <code>Pick&lt;Type, Keys&gt;</code> 从 Type 中选择一组属性来构造新类型。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">Props</span> <span class="token punctuation">{</span>
  id<span class="token operator">:</span> <span class="token builtin">string</span>
  title<span class="token operator">:</span> <span class="token builtin">string</span>
  children<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">PickProps</span> <span class="token operator">=</span> Pick<span class="token operator">&lt;</span>Props<span class="token punctuation">,</span> <span class="token string">'id'</span> <span class="token operator">|</span> <span class="token string">'title'</span><span class="token operator">&gt;</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>Pick 工具类型有两个类型变量：1 表示选择谁的属性 2 表示选择哪几个属性。</p></li> <li><p>其中第二个类型变量，如果只选择一个则只传入该属性名即可。</p></li> <li><p>第二个类型变量传入的属性只能是第一个类型变量中存在的属性。</p></li> <li><p>构造出来的新类型 PickProps，只有 id 和 title 两个属性类型。</p></li></ol></blockquote> <p>泛型工具类型 - <code>Record&lt;Keys,Type&gt;</code> 构造一个对象类型，属性键为 Keys，属性类型为 Type。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">type</span> <span class="token class-name">RecordObj</span> <span class="token operator">=</span> Record<span class="token operator">&lt;</span><span class="token string">'a'</span> <span class="token operator">|</span> <span class="token string">'b'</span> <span class="token operator">|</span> <span class="token string">'c'</span><span class="token punctuation">,</span> <span class="token builtin">string</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token operator">&gt;</span>

<span class="token comment">// type RecordObj = {</span>
<span class="token comment">//   a: string[]</span>
<span class="token comment">//   b: string[]</span>
<span class="token comment">//   c: string[]</span>
<span class="token comment">// }</span>

<span class="token keyword">let</span> obj<span class="token operator">:</span> RecordObj <span class="token operator">=</span> <span class="token punctuation">{</span>
  a<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  b<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'b'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
  c<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'c'</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br><span class="line-number">12</span><br><span class="line-number">13</span><br><span class="line-number">14</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>Record 工具类型有两个类型变量：1 表示对象有哪些属性 2 表示对象属性的类型。</p></li> <li><p>构建的新对象类型 RecordObj 表示：这个对象有三个属性分别为a/b/c，属性值的类型都是 string[]。</p></li></ol></blockquote> <h2 id="_4-5-索引签名类型"><a href="#_4-5-索引签名类型" class="header-anchor">#</a> <strong>4.5 索引签名类型</strong></h2> <p><strong>绝大多数情况下，我们都可以在使用对象前就确定对象的结构，并为对象添加准确的类型。</strong></p> <p><strong>使用场景：当无法确定对象中有哪些属性（或者说对象中可以出现任意多个属性），此时，就用到索引签名类型了。</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">interface</span> <span class="token class-name">AnyObject</span> <span class="token punctuation">{</span>
  <span class="token punctuation">[</span>key<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">]</span><span class="token operator">:</span> <span class="token builtin">number</span>
<span class="token punctuation">}</span>

<span class="token keyword">let</span> obj<span class="token operator">:</span> AnyObject <span class="token operator">=</span> <span class="token punctuation">{</span>
  a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
  abc<span class="token operator">:</span> <span class="token number">124</span><span class="token punctuation">,</span>
  abcde<span class="token operator">:</span> <span class="token number">12345</span>
<span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>使用 [key: string] 来约束该接口中允许出现的属性名称。表示只要是 string 类型的属性名称，都可以出现在对象中。</p></li> <li><p>这样，对象 obj 中就可以出现任意多个属性（比如，a、b 等）。</p></li> <li><p>key 只是一个占位符，可以换成任意合法的变量名称。</p></li> <li><p>隐藏的前置知识：JS 中对象（{}）的键是 string 类型的。</p></li></ol></blockquote> <p><strong>在 JS 中数组是一类特殊的对象，特殊在数组的键（索引）是数值类型。</strong></p> <p><strong>并且，数组也可以出现任意多个元素。所以，在数组对应的泛型接口中，也用到了索引签名类型。</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">const</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span>
arr<span class="token punctuation">.</span>forEach

<span class="token keyword">interface</span> <span class="token class-name">MyArray<span class="token operator">&lt;</span>Type<span class="token operator">&gt;</span></span> <span class="token punctuation">{</span>
  <span class="token punctuation">[</span>index<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">]</span><span class="token operator">:</span> Type
<span class="token punctuation">}</span>
<span class="token keyword">let</span> arr1<span class="token operator">:</span> MyArray<span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">&gt;</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span>
arr1<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span>
</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>MyArray 接口模拟原生的数组接口，并使用 [n: number] 来作为索引签名类型。</p></li> <li><p>该索引签名类型表示：只要是 number 类型的键（索引）都可以出现在数组中，或者说数组中可以有任意多个元素。</p></li> <li><p>同时也符合数组索引是 number 类型这一前提。</p></li></ol></blockquote> <h2 id="_4-6-映射类型"><a href="#_4-6-映射类型" class="header-anchor">#</a> <strong>4.6 映射类型</strong></h2> <p>映射类型：基于旧类型创建新类型（对象类型），减少重复、提升开发效率。</p> <p>比如，类型 PropKeys 有 x/y/z，另一个类型 Type1 中也有 x/y/z，并且 Type1 中 x/y/z 的类型相同：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">type</span> <span class="token class-name">PropKeys</span> <span class="token operator">=</span> <span class="token string">'x'</span> <span class="token operator">|</span> <span class="token string">'y'</span> <span class="token operator">|</span> <span class="token string">'z'</span> <span class="token operator">|</span> <span class="token string">'a'</span> <span class="token operator">|</span> <span class="token string">'b'</span>
<span class="token keyword">type</span> <span class="token class-name">Type1</span> <span class="token operator">=</span> <span class="token punctuation">{</span> x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> z<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> b<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">}</span>
<span class="token comment">// 这样书写没错，但 x/y/z 重复书写了两次。像这种情况，就可以使用映射类型来进行简化。</span>

<span class="token keyword">type</span> <span class="token class-name">Type2</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">[</span>Key <span class="token keyword">in</span> PropKeys<span class="token punctuation">]</span><span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">}</span>

<span class="token comment">// 错误演示：</span>
<span class="token comment">// interface Type3 {</span>
<span class="token comment">//   [Key in PropKeys]: number</span>
<span class="token comment">// }</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>映射类型是基于索引签名类型的，所以，该语法类似于索引签名类型，也使用了 []。</p></li> <li><p>Key <strong>in</strong> PropKeys 表示 Key 可以是 PropKeys 联合类型中的任意一个，类似于 forin(let k in obj)。</p></li> <li><p>使用映射类型创建的新对象类型 Type2 和类型 Type1 结构完全相同。</p></li> <li><p>注意：映射类型只能在类型别名中使用，不能在接口中使用。</p></li></ol></blockquote> <p>映射类型除了根据联合类型创建新类型外，还可以根据对象类型来创建：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">type</span> <span class="token class-name">Props</span> <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> b<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> c<span class="token operator">:</span> <span class="token builtin">boolean</span> <span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">Type3</span> <span class="token operator">=</span> <span class="token punctuation">{</span> <span class="token punctuation">[</span>key <span class="token keyword">in</span> <span class="token keyword">keyof</span> Props<span class="token punctuation">]</span><span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">}</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>首先，先执行 keyof Props 获取到对象类型 Props 中所有键的联合类型即，'a' | 'b' | 'c'。</p></li> <li><p>然后，Key in ... 就表示 Key 可以是 Props 中所有的键名称中的任意一个。</p></li></ol></blockquote> <p><img src="https://img-blog.csdnimg.cn/454c040e8ebd4631836f1aaa84c912a2.png" alt="在这里插入图片描述"></p> <p>实际上，前面讲到的泛型工具类型（比如，<code>Partial&lt;Type&gt;</code>）都是基于映射类型实现的。比如，<code>Partial&lt;Type&gt;</code> 的实现：</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">type</span> <span class="token class-name">Partial<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">&gt;</span></span> <span class="token operator">=</span> <span class="token punctuation">{</span>
    <span class="token punctuation">[</span><span class="token constant">P</span> <span class="token keyword">in</span> <span class="token keyword">keyof</span> <span class="token constant">T</span><span class="token punctuation">]</span><span class="token operator">?</span><span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">[</span><span class="token constant">P</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">Props</span> <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> b<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> c<span class="token operator">:</span> <span class="token builtin">boolean</span> <span class="token punctuation">}</span>
<span class="token keyword">type</span> <span class="token class-name">PartialProps</span> <span class="token operator">=</span> Partial<span class="token operator">&lt;</span>Props<span class="token operator">&gt;</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><blockquote><p>解释：</p> <ol><li><p>keyof T 即 keyof Props 表示获取 Props 的所有键，也就是：'a' | 'b' | 'c'。</p></li> <li><p>在 [] 后面添加 ?（问号），表示将这些属性变为可选的，以此来实现 Partial 的功能。</p></li> <li><p>冒号后面的 <code>T[P]</code> 表示获取 T 中每个键对应的类型。比如，如果是 'a' 则类型是 number；如果是 'b' 则类型是 string。</p></li> <li><p>最终，新类型 PartialProps 和旧类型 Props 结构完全相同，只是让所有类型都变为可选了。</p></li></ol></blockquote> <p>刚刚用到的 <code>T[P]</code> 语法，在 TS 中叫做索引查询（访问）类型。 作用：用来查询属性的类型。</p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">type</span> <span class="token class-name">Props</span> <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> b<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> c<span class="token operator">:</span> <span class="token builtin">boolean</span> <span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">TypeA</span> <span class="token operator">=</span> Props<span class="token punctuation">[</span><span class="token string">'a'</span><span class="token punctuation">]</span>

<span class="token comment">// 模拟 Partial 类型：</span>
<span class="token keyword">type</span> <span class="token class-name">MyPartial<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">&gt;</span></span> <span class="token operator">=</span> <span class="token punctuation">{</span>
  <span class="token punctuation">[</span><span class="token constant">P</span> <span class="token keyword">in</span> <span class="token keyword">keyof</span> <span class="token constant">T</span><span class="token punctuation">]</span><span class="token operator">?</span><span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">[</span><span class="token constant">P</span><span class="token punctuation">]</span>
<span class="token punctuation">}</span>

<span class="token keyword">type</span> <span class="token class-name">PartialProps</span> <span class="token operator">=</span> MyPartial<span class="token operator">&lt;</span>Props<span class="token operator">&gt;</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br><span class="line-number">8</span><br><span class="line-number">9</span><br><span class="line-number">10</span><br><span class="line-number">11</span><br></div></div><blockquote><p>解释：<code>Props['a']</code> 表示查询类型 Props 中属性 'a' 对应的类型 number。所以，TypeA 的类型为 number。</p> <p>注意：[] 中的属性必须存在于被查询类型中，否则就会报错。</p></blockquote> <p><strong>索引查询类型的其他使用方式：同时查询多个索引的类型</strong></p> <div class="language-tsx line-numbers-mode"><pre class="language-tsx"><code><span class="token keyword">type</span> <span class="token class-name">Props</span> <span class="token operator">=</span> <span class="token punctuation">{</span> a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> b<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span> c<span class="token operator">:</span> <span class="token builtin">boolean</span> <span class="token punctuation">}</span>

<span class="token comment">// 其他使用方式：</span>
<span class="token keyword">type</span> <span class="token class-name">TypeA</span> <span class="token operator">=</span> Props<span class="token punctuation">[</span><span class="token string">'a'</span> <span class="token operator">|</span> <span class="token string">'b'</span><span class="token punctuation">]</span>

<span class="token keyword">type</span> <span class="token class-name">TypeB</span> <span class="token operator">=</span> Props<span class="token punctuation">[</span><span class="token keyword">keyof</span> Props<span class="token punctuation">]</span>

</code></pre> <div class="line-numbers-wrapper"><span class="line-number">1</span><br><span class="line-number">2</span><br><span class="line-number">3</span><br><span class="line-number">4</span><br><span class="line-number">5</span><br><span class="line-number">6</span><br><span class="line-number">7</span><br></div></div><blockquote><p>解释：</p> <p>​	1.使用字符串字面量的联合类型，获取属性 a 和 b 对应的类型，结果为： string | number。</p> <p>​	2.使用 keyof 操作符获取 Props 中所有键对应的类型，结果为： string | number | boolean</p></blockquote> <h1 id="_5-typescript-类型声明文件"><a href="#_5-typescript-类型声明文件" class="header-anchor">#</a> <strong>5.TypeScript 类型声明文件</strong></h1> <h2 id="概述-3"><a href="#概述-3" class="header-anchor">#</a> <strong>概述</strong></h2> <blockquote><p>今天几乎所有的 JavaScript 应用都会引入许多第三方库来完成任务需求。</p> <p>这些第三方库不管是否是用 TS 编写的，最终都要编译成 JS 代码，才能发布给开发者使用。</p> <p>我们知道是 TS 提供了类型，才有了代码提示和类型保护等机制。</p> <p>但在项目开发中使用第三方库时，你会发现它们几乎都有相应的 TS 类型，这些类型是怎么来的呢？类型声明文件</p> <p>类型声明文件：用来为已存在的 JS 库提供类型信息。</p> <p>这样在 TS 项目中使用这些库时，就像用 TS 一样，都会有代码提示、类型保护等机制了。</p></blockquote> <p>​	1.TS 的两种文件类型</p> <p>​	2.类型声明文件的使用说明</p> <h2 id="_5-1-ts-中的两种文件类型"><a href="#_5-1-ts-中的两种文件类型" class="header-anchor">#</a> <strong>5.1 TS 中的两种文件类型</strong></h2> <p>TS 中有两种文件类型：1 .ts 文件 2 .d.ts 文件。</p> <ul><li><strong>.ts 文件：</strong></li></ul> <ol><li><p>既包含类型信息又可执行代码。</p></li> <li><p>可以被编译为 .js 文件，然后，执行代码。</p></li> <li><p>用途：编写程序代码的地方。</p></li></ol> <ul><li><strong>.d.ts 文件：</strong></li></ul> <ol><li><p>只包含类型信息的类型声明文件。</p></li> <li><p>不会生成 .js 文件，仅用于提供类型信息。</p></li> <li><p>用途：为 JS 提供类型信息。</p></li></ol> <p><strong>总结：.ts 是 implementation（代码实现文件）；.d.ts 是 declaration（类型声明文件）。如果要为 JS 库提供类型信息，要使用 .d.ts 文件。</strong></p> <h2 id="_5-2-类型声明文件的使用说明"><a href="#_5-2-类型声明文件的使用说明" class="header-anchor">#</a> <strong>5.2 类型声明文件的使用说明</strong></h2> <p>在使用 TS 开发项目时，类型声明文件的使用包括以下两种方式：</p> <ol><li><p>使用已有的类型声明文件</p></li> <li><p>创建自己的类型声明文件</p></li></ol> <p>学习顺序：先会用（别人的）再会写（自己的）。</p> <ul><li><strong>使用已有的类型声明文件：1 内置类型声明文件 2 第三方库的类型声明文件。</strong></li></ul> <ol><li>内置类型声明文件：<strong>TS 为 JS 运行时可用的所有标准化内置 API 都提供了声明文件</strong>。比如，在使用数组时，数组所有方法都会有相应的代码提示以及类型信息：</li></ol> <p><img src="C:%5CUsers%5C85839%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20221102164533403.png" alt="image-20221102164533403"></p> <p>实际上这都是 TS 提供的内置类型声明文件。</p> <p>可以通过 Ctrl + 鼠标左键（Mac：option + 鼠标左键）来查看内置类型声明文件内容。比如，查看 forEach 方法的类型声明，在 VSCode 中会自动跳转到 lib.es5**.d.ts** 类型声明文件中。当然，像 window、document 等 BOM、DOM API 也都有相应的类型声明（lib.dom**.d.ts**）</p> <ol start="2"><li>第三方库的类型声明文件：目前，几乎所有常用的第三方库都有相应的类型声明文件。</li></ol> <p>第三方库的类型声明文件有两种存在形式：1 库自带类型声明文件 2 由 DefinitelyTyped 提供。</p> <ol><li>库自带类型声明文件：比如，axios。</li></ol> <p><img src="C:%5CUsers%5C85839%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20221102164703823.png" alt="image-20221102164703823"></p> <blockquote><p>解释：这种情况下，正常导入该库，TS 就会自动加载库自己的类型声明文件，以提供该库的类型声明。</p></blockquote> <ol start="2"><li><p>由 <a href="https://github.com/DefinitelyTyped/DefinitelyTyped/" target="_blank" rel="noopener noreferrer">DefinitelyTyped<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 提供。</p> <blockquote><p>https://github.com/DefinitelyTyped/DefinitelyTyped/</p></blockquote></li></ol> <p><a href="https://github.com/DefinitelyTyped/DefinitelyTyped/" target="_blank" rel="noopener noreferrer">DefinitelyTyped<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 是一个 github 仓库，用来提供高质量 TypeScript 类型声明。可以通过 npm/yarn 来下载该仓库提供的 TS 类型声明包，这些包的名称格式为：<strong>@types/*</strong>。比如，@types/react、@types/lodash 等。</p> <p>说明：在实际项目开发时，如果你使用的第三方库没有自带的声明文件，VSCode 会给出明确的提示。</p> <p><img src="C:%5CUsers%5C85839%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5Cimage-20221102164931929.png" alt="image-20221102164931929"></p> <blockquote><p>解释：当安装 @types/* 类型声明包后，TS 也会自动加载该类声明包，以提供该库的类型声明。</p> <p>补充：TS 官方文档提供了一个页面，可以来查询 @types/* 库。</p></blockquote> <ul><li><strong>创建自己的类型声明文件：1 项目内共享类型 2 为已有 JS 文件提供类型声明。</strong></li></ul> <ol><li>项目内共享类型：如果多个 .ts 文件中都用到同一个类型，此时可以创建 .d.ts 文件提供该类型，实现类型共享。</li></ol> <p><strong>操作步骤：</strong></p> <ol><li><p>创建 index.d.ts 类型声明文件。</p></li> <li><p>创建需要共享的类型，并使用 export 导出（TS 中的类型也可以使用 import/export 实现模块化功能）。</p></li> <li><p>在需要使用共享类型的 .ts 文件中，通过 import 导入即可（.d.ts 后缀导入时，直接省略）。</p></li></ol> <ul><li>创建自己的类型声明文件：1 项目内共享类型 2 为已有 JS 文件提供类型声明。</li></ul> <ol start="2"><li><p>为已有 JS 文件提供类型声明：</p></li> <li><p>在将 JS 项目迁移到 TS 项目时，为了让已有的 .js 文件有类型声明。</p></li> <li><p>成为库作者，创建库给其他人使用。</p></li></ol> <p>注意：类型声明文件的编写与模块化方式相关，不同的模块化方式有不同的写法。但由于历史原因，JS 模块化的发展 经历过多种变化（AMD、CommonJS、UMD、ESModule 等），而 TS 支持各种模块化形式的类型声明。这就导致，类型声明文件相关内容又多又杂。 演示：基于最新的 ESModule（import/export）来为已有 .js 文件，创建类型声明文件。开发环境准备：使用 webpack 搭建，通过 ts-loader 处理 .ts 文件。</p> <p>说明：TS 项目中也可以使用 .js 文件。</p> <p>说明：在导入 .js 文件时，TS 会自动加载与 .js 同名的 .d.ts 文件，以提供类型声明。</p> <p>declare 关键字：用于类型声明，为其他地方（比如，.js 文件）已存在的变量声明类型，而不是创建一个新的变量。</p> <ol><li><p>对于 type、interface 等这些明确就是 TS 类型的（只能在 TS 中使用的），可以省略 declare 关键字。</p></li> <li><p>对于 let、function 等具有双重含义（在 JS、TS 中都能用），应该使用 declare 关键字，明确指定此处用于类型声明。</p></li></ol></div></section> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">Last Updated: </span> <span class="time">11/21/2022, 2:38:24 PM</span></div></footer> <!----> <div class="comments-wrapper"><!----></div> <ul class="side-bar sub-sidebar-wrapper" style="width:12rem;" data-v-ac050c62><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_1-1-typescript-是什么" class="sidebar-link reco-side-_1-1-typescript-是什么" data-v-ac050c62>1.1 TypeScript 是什么</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_1-2-typescript-为什么要为-js-添加类型支持" class="sidebar-link reco-side-_1-2-typescript-为什么要为-js-添加类型支持" data-v-ac050c62>1.2 TypeScript 为什么要为 JS 添加类型支持？</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_1-3-typescript-相比-js-的优势" class="sidebar-link reco-side-_1-3-typescript-相比-js-的优势" data-v-ac050c62>1.3 TypeScript 相比 JS 的优势</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_2-1-安装编译-ts-的工具包" class="sidebar-link reco-side-_2-1-安装编译-ts-的工具包" data-v-ac050c62>2.1 安装编译 TS 的工具包</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_2-2-编译并运行-ts-代码" class="sidebar-link reco-side-_2-2-编译并运行-ts-代码" data-v-ac050c62>2.2 编译并运行 TS 代码</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_2-3-简化运行-ts-的步骤" class="sidebar-link reco-side-_2-3-简化运行-ts-的步骤" data-v-ac050c62>2.3 简化运行 TS 的步骤</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#概述" class="sidebar-link reco-side-概述" data-v-ac050c62>概述</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-1-类型注解" class="sidebar-link reco-side-_3-1-类型注解" data-v-ac050c62>3.1 类型注解</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-2-常用基础类型概述" class="sidebar-link reco-side-_3-2-常用基础类型概述" data-v-ac050c62>3.2 常用基础类型概述</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-3-原始类型" class="sidebar-link reco-side-_3-3-原始类型" data-v-ac050c62>3.3 原始类型</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-4-数组类型" class="sidebar-link reco-side-_3-4-数组类型" data-v-ac050c62>3.4 数组类型</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-5-类型别名" class="sidebar-link reco-side-_3-5-类型别名" data-v-ac050c62>3.5 类型别名</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-6-函数类型" class="sidebar-link reco-side-_3-6-函数类型" data-v-ac050c62>3.6 函数类型</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-7-对象类型" class="sidebar-link reco-side-_3-7-对象类型" data-v-ac050c62>3.7 对象类型</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-8-接口" class="sidebar-link reco-side-_3-8-接口" data-v-ac050c62>3.8 接口</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-9-元组" class="sidebar-link reco-side-_3-9-元组" data-v-ac050c62>3.9 元组</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-10-类型推论" class="sidebar-link reco-side-_3-10-类型推论" data-v-ac050c62>3.10 类型推论</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-11-类型断言" class="sidebar-link reco-side-_3-11-类型断言" data-v-ac050c62>3.11 类型断言</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-12-字面量类型" class="sidebar-link reco-side-_3-12-字面量类型" data-v-ac050c62>3.12 字面量类型</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-13-枚举" class="sidebar-link reco-side-_3-13-枚举" data-v-ac050c62>3.13 枚举</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-14-any-类型" class="sidebar-link reco-side-_3-14-any-类型" data-v-ac050c62>3.14 any 类型</a></li><li class="level-3" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_3-15-typeof" class="sidebar-link reco-side-_3-15-typeof" data-v-ac050c62>3.15 typeof</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#概述-2" class="sidebar-link reco-side-概述-2" data-v-ac050c62>概述</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_4-1-class-类" class="sidebar-link reco-side-_4-1-class-类" data-v-ac050c62>4.1 class 类</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_4-2-类型兼容性" class="sidebar-link reco-side-_4-2-类型兼容性" data-v-ac050c62>4.2 类型兼容性</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_4-3-交叉类型" class="sidebar-link reco-side-_4-3-交叉类型" data-v-ac050c62>4.3 交叉类型</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_4-4-泛型" class="sidebar-link reco-side-_4-4-泛型" data-v-ac050c62>4.4 泛型</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_4-5-索引签名类型" class="sidebar-link reco-side-_4-5-索引签名类型" data-v-ac050c62>4.5 索引签名类型</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_4-6-映射类型" class="sidebar-link reco-side-_4-6-映射类型" data-v-ac050c62>4.6 映射类型</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#概述-3" class="sidebar-link reco-side-概述-3" data-v-ac050c62>概述</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_5-1-ts-中的两种文件类型" class="sidebar-link reco-side-_5-1-ts-中的两种文件类型" data-v-ac050c62>5.1 TS 中的两种文件类型</a></li><li class="level-2" data-v-ac050c62><a href="/blogs/TypeScript/TypeScript%E5%85%A5%E9%97%A8.html#_5-2-类型声明文件的使用说明" class="sidebar-link reco-side-_5-2-类型声明文件的使用说明" data-v-ac050c62>5.2 类型声明文件的使用说明</a></li></ul></main></div> <!----></div></div></div></div><div class="global-ui"><div class="back-to-ceiling" style="right:1rem;bottom:6rem;width:2.5rem;height:2.5rem;border-radius:.25rem;line-height:2.5rem;display:none;" data-v-c6073ba8 data-v-c6073ba8><svg t="1574745035067" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5404" class="icon" data-v-c6073ba8><path d="M526.60727968 10.90185116a27.675 27.675 0 0 0-29.21455937 0c-131.36607665 82.28402758-218.69155461 228.01873535-218.69155402 394.07834331a462.20625001 462.20625001 0 0 0 5.36959153 69.94390903c1.00431239 6.55289093-0.34802892 13.13561351-3.76865779 18.80351572-32.63518765 54.11355614-51.75690182 118.55860487-51.7569018 187.94566865a371.06718723 371.06718723 0 0 0 11.50484808 91.98906777c6.53300375 25.50556257 41.68394495 28.14064038 52.69160883 4.22606766 17.37162448-37.73630017 42.14135425-72.50938081 72.80769204-103.21549295 2.18761121 3.04276886 4.15646224 6.24463696 6.40373557 9.22774369a1871.4375 1871.4375 0 0 0 140.04691725 5.34970492 1866.36093723 1866.36093723 0 0 0 140.04691723-5.34970492c2.24727335-2.98310674 4.21612437-6.18497483 6.3937923-9.2178004 30.66633723 30.70611158 55.4360664 65.4791928 72.80769147 103.21549355 11.00766384 23.91457269 46.15860503 21.27949489 52.69160879-4.22606768a371.15156223 371.15156223 0 0 0 11.514792-91.99901164c0-69.36717486-19.13165746-133.82216804-51.75690182-187.92578088-3.42062944-5.66790279-4.76302748-12.26056868-3.76865837-18.80351632a462.20625001 462.20625001 0 0 0 5.36959269-69.943909c-0.00994388-166.08943902-87.32547796-311.81420293-218.6915546-394.09823051zM605.93803103 357.87693858a93.93749974 93.93749974 0 1 1-187.89594924 6.1e-7 93.93749974 93.93749974 0 0 1 187.89594924-6.1e-7z" p-id="5405" data-v-c6073ba8></path><path d="M429.50777625 765.63860547C429.50777625 803.39355007 466.44236686 1000.39046097 512.00932183 1000.39046097c45.56695499 0 82.4922232-197.00623328 82.5015456-234.7518555 0-37.75494459-36.9345906-68.35043303-82.4922232-68.34111062-45.57627738-0.00932239-82.52019037 30.59548842-82.51086798 68.34111062z" p-id="5406" data-v-c6073ba8></path></svg></div><div class="kanbanniang" data-v-5775ee02><div class="banniang-container" style="display:;" data-v-5775ee02><div class="messageBox" style="right:68px;bottom:190px;display:none;" data-v-5775ee02>
      欢迎来到 星月前端博客
    </div> <div class="operation" style="right:90px;bottom:40px;display:;" data-v-5775ee02><i class="kbnfont kbn-ban-home ban-home" data-v-5775ee02></i> <i class="kbnfont kbn-ban-message message" data-v-5775ee02></i> <i class="kbnfont kbn-ban-close close" data-v-5775ee02></i> <a target="_blank" href="https://vuepress-theme-reco.recoluan.com/views/plugins/kanbanniang.html" data-v-5775ee02><i class="kbnfont kbn-ban-info info" data-v-5775ee02></i></a> <i class="kbnfont kbn-ban-theme skin" style="display:none;" data-v-5775ee02></i></div> <canvas id="banniang" width="150" height="220" class="live2d" style="right:90px;bottom:-20px;opacity:0.9;" data-v-5775ee02></canvas></div> <div class="showBanNiang" style="display:none;" data-v-5775ee02>
    看板娘
  </div></div><canvas id="vuepress-canvas-cursor"></canvas></div></div>
    <script src="/assets/js/app.b0d6e6c9.js" defer></script><script src="/assets/js/3.3f705cf6.js" defer></script><script src="/assets/js/1.5432b32a.js" defer></script><script src="/assets/js/17.39fb3a22.js" defer></script>
  </body>
</html>
